diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/src/models/ChartPlugin.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/src/models/ChartPlugin.ts index dd84d7709d..0ce60a4dd0 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/src/models/ChartPlugin.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/src/models/ChartPlugin.ts @@ -1,4 +1,4 @@ -import { FunctionComponent, ComponentType } from 'react'; +import { ComponentType } from 'react'; import { isRequired, Plugin } from '@superset-ui/core'; import { QueryFormData } from '@superset-ui/query'; import ChartMetadata from './ChartMetadata'; @@ -18,7 +18,7 @@ const EMPTY = {}; export type PromiseOrValue = Promise | T; export type PromiseOrValueLoader = () => PromiseOrValue; -export type ChartType = ComponentType | FunctionComponent; +export type ChartType = ComponentType; type ValueOrModuleWithValue = T | { default: T }; interface ChartPluginConfig { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/ChartDataProvider.test.tsx b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/ChartDataProvider.test.tsx index 37c39931c8..208525c810 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/ChartDataProvider.test.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/ChartDataProvider.test.tsx @@ -4,16 +4,21 @@ import ChartClient from '../../src/clients/ChartClient'; import ChartDataProvider, { Props } from '../../src/components/ChartDataProvider'; import { bigNumberFormData } from '../fixtures/formData'; -// Note: the mock implentatino of these function directly affects the expected results below -const defaultMockLoadFormData = jest.fn(allProps => Promise.resolve(allProps.formData)); +// Note: the mock implementation of these function directly affects the expected results below +const defaultMockLoadFormData = jest.fn(({ formData }: { formData: unknown }) => + Promise.resolve(formData), +); -// coerce here else get: Type 'Mock, []>' is not assignable to type 'Mock, any[]>' -let mockLoadFormData = defaultMockLoadFormData as jest.Mock, any>; -const mockLoadDatasource = jest.fn(datasource => Promise.resolve(datasource)) as jest.Mock< - Promise, - any ->; -const mockLoadQueryData = jest.fn(input => Promise.resolve(input)) as jest.Mock, any>; +type MockLoadFormData = typeof defaultMockLoadFormData | jest.Mock, unknown[]>; + +let mockLoadFormData: MockLoadFormData = defaultMockLoadFormData; + +function createPromise(input: T, ..._args: unknown[]) { + return Promise.resolve(input); +} + +const mockLoadDatasource = jest.fn, unknown[]>(createPromise); +const mockLoadQueryData = jest.fn, unknown[]>(createPromise); // ChartClient is now a mock jest.mock('../../src/clients/ChartClient', () => @@ -177,7 +182,7 @@ describe('ChartDataProvider', () => { describe('children', () => { it('calls children({ loading: true }) when loading', () => { - const children = jest.fn(); + const children = jest.fn(); setup({ children }); // during the first tick (before more promises resolve) loading is true @@ -188,7 +193,7 @@ describe('ChartDataProvider', () => { it('calls children({ payload }) when loaded', () => { return new Promise(done => { expect.assertions(2); - const children = jest.fn(); + const children = jest.fn(); setup({ children, loadDatasource: true }); setTimeout(() => { @@ -208,7 +213,7 @@ describe('ChartDataProvider', () => { it('calls children({ error }) upon request error', () => { return new Promise(done => { expect.assertions(2); - const children = jest.fn(); + const children = jest.fn(); mockLoadFormData = jest.fn(() => Promise.reject(new Error('error'))); setup({ children }); @@ -224,7 +229,7 @@ describe('ChartDataProvider', () => { it('calls children({ error }) upon JS error', () => { return new Promise(done => { expect.assertions(2); - const children = jest.fn(); + const children = jest.fn(); mockLoadFormData = jest.fn(() => { throw new Error('non-async error'); @@ -245,7 +250,7 @@ describe('ChartDataProvider', () => { it('calls onLoad(payload) when loaded', () => { return new Promise(done => { expect.assertions(2); - const onLoaded = jest.fn(); + const onLoaded = jest.fn(); setup({ onLoaded, loadDatasource: true }); setTimeout(() => { @@ -263,7 +268,7 @@ describe('ChartDataProvider', () => { it('calls onError(error) upon request error', () => { return new Promise(done => { expect.assertions(2); - const onError = jest.fn(); + const onError = jest.fn(); mockLoadFormData = jest.fn(() => Promise.reject(new Error('error'))); setup({ onError }); @@ -278,7 +283,7 @@ describe('ChartDataProvider', () => { it('calls onError(error) upon JS error', () => { return new Promise(done => { expect.assertions(2); - const onError = jest.fn(); + const onError = jest.fn(); mockLoadFormData = jest.fn(() => { throw new Error('non-async error'); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/MockChartPlugins.tsx b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/MockChartPlugins.tsx index 6ac325ae2b..657ebb40cc 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/MockChartPlugins.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/MockChartPlugins.tsx @@ -17,7 +17,7 @@ export const TestComponent = ({ width, height, }: { - formData?: any; + formData?: unknown; message?: string; width?: number; height?: number; @@ -67,6 +67,10 @@ export class DiligentChartPlugin extends ChartPlugin { } } +function identity(x: T) { + return x; +} + export class LazyChartPlugin extends ChartPlugin { constructor() { super({ @@ -77,7 +81,7 @@ export class LazyChartPlugin extends ChartPlugin { // this mirrors `() => import(module)` syntax loadChart: () => Promise.resolve({ default: TestComponent }), // promise without .default - loadTransformProps: () => Promise.resolve((x: any) => x), + loadTransformProps: () => Promise.resolve(identity), }); } } diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/createLoadableRenderer.test.tsx b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/createLoadableRenderer.test.tsx index 38cdd1309e..d48d77d498 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/createLoadableRenderer.test.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-chart/test/components/createLoadableRenderer.test.tsx @@ -10,7 +10,7 @@ describe('createLoadableRenderer', () => { return
test
; } let loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent)); - let render: (loaded: { [key: string]: any }) => JSX.Element; + let render: (loaded: { Chart: React.ComponentType }) => JSX.Element; let loading: () => JSX.Element; let LoadableRenderer: LoadableRendererType<{}, {}>; let restoreConsole: RestoreConsole; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/callApi/callApi.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/callApi/callApi.ts index 957be1563e..63c4bd410d 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/callApi/callApi.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/callApi/callApi.ts @@ -79,6 +79,7 @@ export default function callApi({ Object.keys(postPayload).forEach(key => { const value = postPayload[key]; if (typeof value !== 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call formData.append(key, stringify ? JSON.stringify(value) : value); } }); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/types.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/types.ts index 0b4467ffd3..964f83c562 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/types.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/src/types.ts @@ -11,8 +11,10 @@ export type FetchRetryOptions = { }; export type Headers = { [k: string]: string }; export type Host = string; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type Json = { [k: string]: any }; export type Method = RequestInit['method']; +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type PostPayload = { [key: string]: any }; export type Mode = RequestInit['mode']; export type Redirect = RequestInit['redirect']; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClient.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClient.test.ts index a4148dd762..7275b112b8 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClient.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClient.test.ts @@ -13,14 +13,14 @@ describe('SupersetClient', () => { afterEach(SupersetClient.reset); it('exposes reset, configure, init, get, post, isAuthenticated, and reAuthenticate methods', () => { - expect(SupersetClient.configure).toEqual(expect.any(Function)); - expect(SupersetClient.init).toEqual(expect.any(Function)); - expect(SupersetClient.get).toEqual(expect.any(Function)); - expect(SupersetClient.post).toEqual(expect.any(Function)); - expect(SupersetClient.isAuthenticated).toEqual(expect.any(Function)); - expect(SupersetClient.reAuthenticate).toEqual(expect.any(Function)); - expect(SupersetClient.request).toEqual(expect.any(Function)); - expect(SupersetClient.reset).toEqual(expect.any(Function)); + expect(typeof SupersetClient.configure).toBe('function'); + expect(typeof SupersetClient.init).toBe('function'); + expect(typeof SupersetClient.get).toBe('function'); + expect(typeof SupersetClient.post).toBe('function'); + expect(typeof SupersetClient.isAuthenticated).toBe('function'); + expect(typeof SupersetClient.reAuthenticate).toBe('function'); + expect(typeof SupersetClient.request).toBe('function'); + expect(typeof SupersetClient.reset).toBe('function'); }); it('throws if you call init, get, post, isAuthenticated, or reAuthenticate before configure', () => { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClientClass.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClientClass.test.ts index 6d9ab26789..f12c7869c3 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClientClass.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/SupersetClientClass.test.ts @@ -100,7 +100,7 @@ describe('SupersetClientClass', () => { return new SupersetClientClass({}) .init() .then(throwIfCalled) - .catch(error => { + .catch((error: { status: number }) => { expect(error.status).toBe(403); return true; @@ -114,7 +114,7 @@ describe('SupersetClientClass', () => { return new SupersetClientClass({}) .init() .then(throwIfCalled) - .catch(error => { + .catch((error: unknown) => { expect(error).toBeDefined(); return true; @@ -129,7 +129,7 @@ describe('SupersetClientClass', () => { return new SupersetClientClass({}) .init() .then(throwIfCalled) - .catch(error => { + .catch((error: unknown) => { expect(error).toBeDefined(); return true; @@ -171,8 +171,10 @@ describe('SupersetClientClass', () => { return client .ensureAuth() .then(throwIfCalled) - .catch(error => { - expect(error).toEqual(expect.objectContaining({ error: expect.any(String) })); + .catch((error: { error: string }) => { + expect(error).toEqual( + expect.objectContaining({ error: expect.any(String) }) as typeof error, + ); expect(client.isAuthenticated()).toBe(false); return true; @@ -209,14 +211,14 @@ describe('SupersetClientClass', () => { return client .init() .then(throwIfCalled) - .catch(error => { - expect(error).toEqual(expect.objectContaining(rejectValue)); + .catch((error: unknown) => { + expect(error).toEqual(expect.objectContaining(rejectValue) as unknown); return client .ensureAuth() .then(throwIfCalled) - .catch(error2 => { - expect(error2).toEqual(expect.objectContaining(rejectValue)); + .catch((error2: unknown) => { + expect(error2).toEqual(expect.objectContaining(rejectValue) as unknown); expect(client.isAuthenticated()).toBe(false); // reset @@ -305,7 +307,7 @@ describe('SupersetClientClass', () => { expect(fetchRequest.mode).toBe(clientConfig.mode); expect(fetchRequest.credentials).toBe(clientConfig.credentials); expect(fetchRequest.headers).toEqual( - expect.objectContaining(clientConfig.headers as Object), + expect.objectContaining(clientConfig.headers) as typeof fetchRequest.headers, ); return true; @@ -379,7 +381,7 @@ describe('SupersetClientClass', () => { expect(fetchRequest.mode).toBe(overrideConfig.mode); expect(fetchRequest.credentials).toBe(overrideConfig.credentials); expect(fetchRequest.headers).toEqual( - expect.objectContaining(overrideConfig.headers as Object), + expect.objectContaining(overrideConfig.headers) as typeof fetchRequest.headers, ); return true; @@ -431,7 +433,7 @@ describe('SupersetClientClass', () => { expect(fetchRequest.mode).toBe(overrideConfig.mode); expect(fetchRequest.credentials).toBe(overrideConfig.credentials); expect(fetchRequest.headers).toEqual( - expect.objectContaining(overrideConfig.headers as Object), + expect.objectContaining(overrideConfig.headers) as typeof fetchRequest.headers, ); return true; @@ -456,15 +458,15 @@ describe('SupersetClientClass', () => { it('passes postPayload key,values in the body', () => { expect.assertions(3); - const postPayload = { number: 123, array: [1, 2, 3] } as any; + const postPayload = { number: 123, array: [1, 2, 3] }; const client = new SupersetClientClass({ protocol, host }); return client.init().then(() => client.post({ url: mockPostUrl, postPayload }).then(() => { const formData = fetchMock.calls(mockPostUrl)[0][1].body as FormData; expect(fetchMock.calls(mockPostUrl)).toHaveLength(1); - Object.keys(postPayload).forEach(key => { - expect(formData.get(key)).toBe(JSON.stringify(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(formData.get(key)).toBe(JSON.stringify(value)); }); return true; @@ -474,15 +476,15 @@ describe('SupersetClientClass', () => { it('respects the stringify parameter for postPayload key,values', () => { expect.assertions(3); - const postPayload = { number: 123, array: [1, 2, 3] } as any; + const postPayload = { number: 123, array: [1, 2, 3] }; const client = new SupersetClientClass({ protocol, host }); return client.init().then(() => client.post({ url: mockPostUrl, postPayload, stringify: false }).then(() => { const formData = fetchMock.calls(mockPostUrl)[0][1].body as FormData; expect(fetchMock.calls(mockPostUrl)).toHaveLength(1); - Object.keys(postPayload).forEach(key => { - expect(formData.get(key)).toBe(String(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(formData.get(key)).toBe(String(value)); }); return true; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApi.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApi.test.ts index 1d5fcd8db0..f71d9109fb 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApi.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApi.test.ts @@ -88,7 +88,9 @@ describe('callApi()', () => { expect(fetchParams.mode).toBe(mockRequest.mode); expect(fetchParams.cache).toBe(mockRequest.cache); expect(fetchParams.credentials).toBe(mockRequest.credentials); - expect(fetchParams.headers).toEqual(expect.objectContaining(mockRequest.headers as Object)); + expect(fetchParams.headers).toEqual( + expect.objectContaining(mockRequest.headers) as typeof fetchParams.headers, + ); expect(fetchParams.redirect).toBe(mockRequest.redirect); expect(fetchParams.signal).toBe(mockRequest.signal); expect(fetchParams.body).toBe(mockRequest.body); @@ -101,7 +103,7 @@ describe('callApi()', () => { describe('POST requests', () => { it('encodes key,value pairs from postPayload', () => { expect.assertions(3); - const postPayload = { key: 'value', anotherKey: 1237 } as any; + const postPayload = { key: 'value', anotherKey: 1237 }; return callApi({ url: mockPostUrl, method: 'POST', postPayload }).then(() => { const calls = fetchMock.calls(mockPostUrl); @@ -110,8 +112,8 @@ describe('callApi()', () => { const fetchParams = calls[0][1]; const body = fetchParams.body as FormData; - Object.keys(postPayload).forEach(key => { - expect(body.get(key)).toBe(JSON.stringify(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(body.get(key)).toBe(JSON.stringify(value)); }); return true; @@ -144,7 +146,7 @@ describe('callApi()', () => { object: { a: 'a', 1: 1 }, null: null, emptyString: '', - } as any; + }; expect.assertions(1 + 2 * Object.keys(postPayload).length); @@ -158,9 +160,9 @@ describe('callApi()', () => { const stringified = calls[0][1].body as FormData; const unstringified = calls[1][1].body as FormData; - Object.keys(postPayload).forEach(key => { - expect(stringified.get(key)).toBe(JSON.stringify(postPayload[key])); - expect(unstringified.get(key)).toBe(String(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(stringified.get(key)).toBe(JSON.stringify(value)); + expect(unstringified.get(key)).toBe(String(value)); }); return true; @@ -171,7 +173,7 @@ describe('callApi()', () => { describe('PUT requests', () => { it('encodes key,value pairs from postPayload', () => { expect.assertions(3); - const postPayload = { key: 'value', anotherKey: 1237 } as any; + const postPayload = { key: 'value', anotherKey: 1237 }; return callApi({ url: mockPutUrl, method: 'PUT', postPayload }).then(() => { const calls = fetchMock.calls(mockPutUrl); @@ -180,8 +182,8 @@ describe('callApi()', () => { const fetchParams = calls[0][1]; const body = fetchParams.body as FormData; - Object.keys(postPayload).forEach(key => { - expect(body.get(key)).toBe(JSON.stringify(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(body.get(key)).toBe(JSON.stringify(value)); }); return true; @@ -214,7 +216,7 @@ describe('callApi()', () => { object: { a: 'a', 1: 1 }, null: null, emptyString: '', - } as any; + }; expect.assertions(1 + 2 * Object.keys(postPayload).length); @@ -228,9 +230,9 @@ describe('callApi()', () => { const stringified = calls[0][1].body as FormData; const unstringified = calls[1][1].body as FormData; - Object.keys(postPayload).forEach(key => { - expect(stringified.get(key)).toBe(JSON.stringify(postPayload[key])); - expect(unstringified.get(key)).toBe(String(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(stringified.get(key)).toBe(JSON.stringify(value)); + expect(unstringified.get(key)).toBe(String(value)); }); return true; @@ -241,7 +243,7 @@ describe('callApi()', () => { describe('PATCH requests', () => { it('encodes key,value pairs from postPayload', () => { expect.assertions(3); - const postPayload = { key: 'value', anotherKey: 1237 } as any; + const postPayload = { key: 'value', anotherKey: 1237 }; return callApi({ url: mockPatchUrl, method: 'PATCH', postPayload }).then(() => { const calls = fetchMock.calls(mockPatchUrl); @@ -250,8 +252,8 @@ describe('callApi()', () => { const fetchParams = calls[0][1]; const body = fetchParams.body as FormData; - Object.keys(postPayload).forEach(key => { - expect(body.get(key)).toBe(JSON.stringify(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(body.get(key)).toBe(JSON.stringify(value)); }); return true; @@ -284,7 +286,7 @@ describe('callApi()', () => { object: { a: 'a', 1: 1 }, null: null, emptyString: '', - } as any; + }; expect.assertions(1 + 2 * Object.keys(postPayload).length); @@ -298,9 +300,9 @@ describe('callApi()', () => { const stringified = calls[0][1].body as FormData; const unstringified = calls[1][1].body as FormData; - Object.keys(postPayload).forEach(key => { - expect(stringified.get(key)).toBe(JSON.stringify(postPayload[key])); - expect(unstringified.get(key)).toBe(String(postPayload[key])); + Object.entries(postPayload).forEach(([key, value]) => { + expect(stringified.get(key)).toBe(JSON.stringify(value)); + expect(unstringified.get(key)).toBe(String(value)); }); return true; @@ -389,7 +391,9 @@ describe('callApi()', () => { const fetchParams = calls[1][1]; const headers = { 'If-None-Match': 'etag' }; expect(calls).toHaveLength(2); - expect(fetchParams.headers).toEqual(expect.objectContaining(headers)); + expect(fetchParams.headers).toEqual( + expect.objectContaining(headers) as typeof fetchParams.headers, + ); return true; }); @@ -417,11 +421,13 @@ describe('callApi()', () => { const mockCachedPayload = { status: 304 }; fetchMock.get(mockUncachedUrl, mockCachedPayload); - return callApi({ url: mockUncachedUrl, method: 'GET' }).catch(error => { - const calls = fetchMock.calls(mockUncachedUrl); - expect(calls).toHaveLength(1); - expect(error.message).toEqual('Received 304 but no content is cached!'); - }); + return callApi({ url: mockUncachedUrl, method: 'GET' }).catch( + (error: { message: string }) => { + const calls = fetchMock.calls(mockUncachedUrl); + expect(calls).toHaveLength(1); + expect(error.message).toEqual('Received 304 but no content is cached!'); + }, + ); }); it('returns original response if no Etag', async () => { @@ -431,7 +437,7 @@ describe('callApi()', () => { expect(calls).toHaveLength(1); expect(response.status).toEqual(200); const body = await response.json(); - expect(body).toEqual(mockGetPayload); + expect(body as typeof mockGetPayload).toEqual(mockGetPayload); }); it('returns original response if status not 304 or 200', async () => { @@ -452,7 +458,7 @@ describe('callApi()', () => { method: 'GET', }) .then(throwIfCalled) - .catch(error => { + .catch((error: { status: number; statusText: string }) => { expect(fetchMock.calls(mockErrorUrl)).toHaveLength(4); expect(error.status).toBe(mockErrorPayload.status); expect(error.statusText).toBe(mockErrorPayload.statusText); @@ -468,7 +474,7 @@ describe('callApi()', () => { method: 'GET', }) .then(throwIfCalled) - .catch(error => { + .catch((error: { status: number; statusText: string }) => { expect(fetchMock.calls(mockErrorUrl)).toHaveLength(1); expect(error.status).toBe(mockErrorPayload.status); expect(error.statusText).toBe(mockErrorPayload.statusText); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApiAndParseWithTimeout.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApiAndParseWithTimeout.test.ts index dfd6568659..e127dbeca6 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApiAndParseWithTimeout.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/callApiAndParseWithTimeout.test.ts @@ -76,9 +76,9 @@ describe('callApiAndParseWithTimeout()', () => { callApiAndParseWithTimeout({ url: mockTimeoutUrl, method: 'GET', timeout: 1 }) .then(throwIfCalled) - .catch(error => { + .catch((error: { error: string; statusText: string }) => { expect(fetchMock.calls(mockTimeoutUrl)).toHaveLength(1); - expect(Object.keys(error)).toEqual(expect.arrayContaining(['error', 'statusText'])); + expect(Object.keys(error)).toEqual(['error', 'statusText']); expect(error.statusText).toBe('timeout'); return done(); // eslint-disable-line promise/no-callback-in-promise @@ -93,6 +93,7 @@ describe('callApiAndParseWithTimeout()', () => { return callApiAndParseWithTimeout({ url: mockGetUrl, method: 'GET', timeout: 100 }).then( (response: Json) => { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call expect(response.json).toEqual(expect.objectContaining(mockGetPayload)); return true; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/parseResponse.test.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/parseResponse.test.ts index 45621e0164..105b64c43b 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/parseResponse.test.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-connection/test/callApi/parseResponse.test.ts @@ -32,17 +32,19 @@ describe('parseResponse()', () => { it('returns a Promise', () => { const apiPromise = callApi({ url: mockGetUrl, method: 'GET' }); const parsedResponsePromise = parseResponse(apiPromise); - expect(parsedResponsePromise).toEqual(expect.any(Promise)); + expect(parsedResponsePromise).toBeInstanceOf(Promise); }); it('resolves to { json, response } if the request succeeds', () => { - expect.assertions(3); + expect.assertions(4); const apiPromise = callApi({ url: mockGetUrl, method: 'GET' }); return parseResponse(apiPromise).then(args => { expect(fetchMock.calls(mockGetUrl)).toHaveLength(1); - expect(Object.keys(args)).toEqual(expect.arrayContaining(['response', 'json'])); - expect(args.json).toEqual(expect.objectContaining(mockGetPayload)); + const keys = Object.keys(args); + expect(keys).toContain('response'); + expect(keys).toContain('json'); + expect(args.json).toEqual(expect.objectContaining(mockGetPayload) as typeof args.json); return true; }); @@ -60,7 +62,7 @@ describe('parseResponse()', () => { return parseResponse(apiPromise, 'json') .then(throwIfCalled) - .catch(error => { + .catch((error: { stack: unknown; message: string }) => { expect(fetchMock.calls(mockTextUrl)).toHaveLength(1); expect(error.stack).toBeDefined(); expect(error.message).toContain('Unexpected token'); @@ -70,7 +72,7 @@ describe('parseResponse()', () => { }); it('resolves to { text, response } if the `parseMethod=text`', () => { - expect.assertions(3); + expect.assertions(4); // test with json + bigint to ensure that it was not first parsed as json const mockTextParseUrl = '/mock/textparse/url'; @@ -81,7 +83,9 @@ describe('parseResponse()', () => { return parseResponse(apiPromise, 'text').then(args => { expect(fetchMock.calls(mockTextParseUrl)).toHaveLength(1); - expect(Object.keys(args)).toEqual(expect.arrayContaining(['response', 'text'])); + const keys = Object.keys(args); + expect(keys).toContain('response'); + expect(keys).toContain('text'); expect(args.text).toBe(mockTextJsonResponse); return true; @@ -118,7 +122,7 @@ describe('parseResponse()', () => { return parseResponse(apiPromise) .then(throwIfCalled) - .catch(error => { + .catch((error: { ok: boolean; status: number }) => { expect(fetchMock.calls(mockNotOkayUrl)).toHaveLength(1); expect(error.ok).toBe(false); expect(error.status).toBe(404); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/Translator.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/Translator.ts index e1eee46642..7a564d4148 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/Translator.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/Translator.ts @@ -4,7 +4,7 @@ import { TranslatorConfig } from './types'; interface Jed { translate(input: string): Jed; ifPlural(value: number, plural: string): Jed; - fetch(...args: any[]): string; + fetch(...args: unknown[]): string; } const DEFAULT_LANGUAGE_PACK = { @@ -25,14 +25,20 @@ export default class Translator { constructor(config: TranslatorConfig = {}) { const { languagePack = DEFAULT_LANGUAGE_PACK } = config; + // eslint-disable-next-line @typescript-eslint/no-unsafe-call this.i18n = new UntypedJed(languagePack) as Jed; } - translate(input: string, ...args: any[]): string { + translate(input: string, ...args: unknown[]): string { return this.i18n.translate(input).fetch(...args); } - translateWithNumber(singular: string, plural: string, num: number = 0, ...args: any[]): string { + translateWithNumber( + singular: string, + plural: string, + num: number = 0, + ...args: unknown[] + ): string { return this.i18n .translate(singular) .ifPlural(num, plural) diff --git a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/TranslatorSingleton.ts b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/TranslatorSingleton.ts index c9eeee62ea..50b134bfaa 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/TranslatorSingleton.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/packages/superset-ui-translation/src/TranslatorSingleton.ts @@ -25,12 +25,12 @@ function getInstance() { return singleton; } -function t(input: string, ...args: any[]) { +function t(input: string, ...args: unknown[]) { return getInstance().translate(input, ...args); } -function tn(singular: string, plural: string, ...args: any[]) { - return getInstance().translateWithNumber(singular, plural, ...args); +function tn(singular: string, plural: string, num?: number, ...args: unknown[]) { + return getInstance().translateWithNumber(singular, plural, num, ...args); } export { configure, t, tn }; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/legacy-plugin-chart-table/src/ReactDataTable.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/legacy-plugin-chart-table/src/ReactDataTable.tsx index 9f84f8c682..fa3fc56d3e 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/legacy-plugin-chart-table/src/ReactDataTable.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/legacy-plugin-chart-table/src/ReactDataTable.tsx @@ -35,7 +35,9 @@ import { DataTableProps } from './transformProps'; // Depending on how the modules are imported, `dt` may be a CommonJS init function, // or the DataTable class itself. In case it is the former, we'd need to tell it // where is jQuery. +// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access if (!dt.$) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call dt(window, $); } @@ -286,6 +288,7 @@ export default function ReactDataTable(props: DataTableProps) { ({ + const data = (queryData.data || []).map(({ label, values }) => ({ label, min: values.whisker_low, max: values.whisker_high, @@ -35,7 +49,14 @@ export default function transformProps(chartProps: ChartProps) { })); const xAxisLabel = groupby.join('/'); - const yAxisLabel = metrics.length > 0 ? verboseMap[metrics[0]] || metrics[0] : ''; + + let metric: QueryFormDataMetric = ''; + if (Array.isArray(metrics)) { + metric = metrics.length > 0 ? metrics[0] : ''; + } else { + metric = metrics; + } + const yAxisLabel = typeof metric === 'string' ? verboseMap[metric] || metric : metric.label; const boxPlotValues = data.reduce((r: number[], e: BoxPlotDataRow) => { r.push(e.min, e.max, ...e.outliers); diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/BoxPlot/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/BoxPlot/transformProps.ts index 8d5eb96ed6..eb5abb463e 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/BoxPlot/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/BoxPlot/transformProps.ts @@ -2,10 +2,12 @@ import { pick } from 'lodash'; import { ChartProps } from '@superset-ui/chart'; import { BoxPlotDataRow, RawBoxPlotDataRow } from '../components/BoxPlot/types'; import { HookProps } from '../components/BoxPlot/BoxPlot'; +import { BoxPlotEncoding } from '../components/BoxPlot/Encoder'; export default function transformProps(chartProps: ChartProps) { const { width, height, formData, queryData } = chartProps; - const { encoding, margin, theme } = formData; + const { margin, theme } = formData; + const encoding = formData.encoding as BoxPlotEncoding; const data = (queryData.data as RawBoxPlotDataRow[]).map(({ label, values }) => ({ label, @@ -33,9 +35,15 @@ export default function transformProps(chartProps: ChartProps) { ]; if (isHorizontal) { - encoding.x.scale.domain = valueDomain; - } else { + if (encoding.x.scale) { + encoding.x.scale.domain = valueDomain; + } else { + encoding.x.scale = { domain: valueDomain }; + } + } else if (encoding.y.scale) { encoding.y.scale.domain = valueDomain; + } else { + encoding.y.scale = { domain: valueDomain }; } const hooks = chartProps.hooks as HookProps; diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/ScatterPlot/legacy/transformProps.ts b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/ScatterPlot/legacy/transformProps.ts index dfd6c7b935..ea2344dc17 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/ScatterPlot/legacy/transformProps.ts +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/ScatterPlot/legacy/transformProps.ts @@ -1,35 +1,39 @@ import { ChartProps } from '@superset-ui/chart'; import { flatMap } from 'lodash'; +interface Value { + [key: string]: unknown; +} + +type Key = keyof Value; + interface DataRow { key: string[]; - values: { - [key: string]: any; - }[]; + values: Value[]; } export default function transformProps(chartProps: ChartProps) { const { width, height, formData, queryData } = chartProps; const { colorScheme, - entity, maxBubbleSize, - series, showLegend, - size, - x, xAxisFormat, xAxisLabel, // TODO: These fields are not supported yet // xAxisShowminmax, // xLogScale, - y, yAxisLabel, yAxisFormat, // TODO: These fields are not supported yet // yAxisShowminmax, // yLogScale, } = formData; + const x = formData.x as Key; + const y = formData.y as Key; + const series = formData.series as Key; + const size = formData.size as Key; + const entity = formData.entity as Key; const data = queryData.data as DataRow[]; return { diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/BoxPlot/BoxPlot.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/BoxPlot/BoxPlot.tsx index 8c7e971e4c..6af6fe2361 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/BoxPlot/BoxPlot.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/BoxPlot/BoxPlot.tsx @@ -85,7 +85,9 @@ export default class BoxPlot extends React.PureComponent { )} theme={theme} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any xScale={convertScaleToDataUIScale(channels.x.definition.scale as any)} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any yScale={convertScaleToDataUIScale(channels.y.definition.scale as any)} > {layout.renderXAxis()} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/Line/Line.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/Line/Line.tsx index b4fdcb06c0..eb5ef3c32e 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/Line/Line.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/Line/Line.tsx @@ -225,9 +225,9 @@ export default class LineChart extends PureComponent { onMouseMove, tooltipData, }: { - onMouseLeave: (...args: any[]) => void; - onMouseMove: (...args: any[]) => void; - tooltipData: any; + onMouseLeave: (...args: unknown[]) => void; + onMouseMove: (...args: unknown[]) => void; + tooltipData: { datum: { y?: number } }; }) => ( { renderTooltip={null} theme={theme} tooltipData={tooltipData} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any xScale={convertScaleToDataUIScale(channels.x.definition.scale as any)} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any yScale={convertScaleToDataUIScale(channels.y.definition.scale as any)} onMouseMove={onMouseMove} onMouseLeave={onMouseLeave} diff --git a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/ScatterPlot/ScatterPlot.tsx b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/ScatterPlot/ScatterPlot.tsx index f592f79ce3..ce7dfbee19 100644 --- a/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/ScatterPlot/ScatterPlot.tsx +++ b/superset-frontend/temporary_superset_ui/superset-ui/plugins/preset-chart-xy/src/components/ScatterPlot/ScatterPlot.tsx @@ -87,7 +87,9 @@ export default class ScatterPlot extends PureComponent { )} theme={theme} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any xScale={convertScaleToDataUIScale(channels.x.definition.scale as any)} + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-explicit-any yScale={convertScaleToDataUIScale(channels.y.definition.scale as any)} > {layout.renderXAxis()}