mirror of
https://github.com/apache/superset.git
synced 2026-05-13 11:55:16 +00:00
Compare commits
16 Commits
fix/mcp-ex
...
feat/migra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5061776835 | ||
|
|
f26e2fa67e | ||
|
|
17bdfaa3ae | ||
|
|
ee00e369fe | ||
|
|
0100a0386b | ||
|
|
4c5936249c | ||
|
|
d9b1de9e75 | ||
|
|
c80961ea91 | ||
|
|
37328866b3 | ||
|
|
9616a7c375 | ||
|
|
a96259dcfc | ||
|
|
6be13ab782 | ||
|
|
f072c6059b | ||
|
|
ea81614206 | ||
|
|
4d05cdd78b | ||
|
|
1565fd7f7a |
32
.github/workflows/superset-frontend.yml
vendored
32
.github/workflows/superset-frontend.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
||||
name: docker-image
|
||||
path: docker-image.tar.gz
|
||||
|
||||
sharded-jest-tests:
|
||||
sharded-unit-tests:
|
||||
needs: frontend-build
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
strategy:
|
||||
@@ -84,19 +84,20 @@ jobs:
|
||||
run: |
|
||||
mkdir -p ${{ github.workspace }}/superset-frontend/coverage
|
||||
docker run \
|
||||
-v ${{ github.workspace }}/superset-frontend/coverage:/app/superset-frontend/coverage \
|
||||
-v ${{ github.workspace }}/superset-frontend/.vitest-reports:/app/superset-frontend/.vitest-reports \
|
||||
--rm $TAG \
|
||||
bash -c \
|
||||
"npm run test -- --coverage --shard=${{ matrix.shard }}/8 --coverageReporters=json"
|
||||
"npm run test -- --coverage.enabled --reporter=blob --shard=${{ matrix.shard }}/8"
|
||||
|
||||
- name: Upload Coverage Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: coverage-artifacts-${{ matrix.shard }}
|
||||
path: superset-frontend/coverage
|
||||
name: blob-report-${{ matrix.shard }}
|
||||
path: .vitest-reports/*
|
||||
include-hidden-files: true
|
||||
|
||||
report-coverage:
|
||||
needs: [sharded-jest-tests]
|
||||
needs: [sharded-unit-tests]
|
||||
if: needs.frontend-build.outputs.should-run == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
@@ -112,19 +113,12 @@ jobs:
|
||||
- name: Download Coverage Artifacts
|
||||
uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: coverage-artifacts-*
|
||||
path: coverage/
|
||||
pattern: blob-report-*
|
||||
path: .vitest-reports
|
||||
merge-multiple: true
|
||||
|
||||
- name: Reorganize test result reports
|
||||
run: |
|
||||
find coverage/
|
||||
for i in {1..8}; do
|
||||
mv coverage/coverage-artifacts-${i}/coverage-final.json coverage/coverage-shard-${i}.json
|
||||
done
|
||||
shell: bash
|
||||
|
||||
- name: Merge Code Coverage
|
||||
run: npx nyc merge coverage/ merged-output/coverage-summary.json
|
||||
- name: Merge reports
|
||||
run: npx vitest --merge-reports
|
||||
|
||||
- name: Upload Code Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
@@ -132,8 +126,6 @@ jobs:
|
||||
flags: javascript
|
||||
use_oidc: true
|
||||
verbose: true
|
||||
disable_search: true
|
||||
files: merged-output/coverage-summary.json
|
||||
slug: apache/superset
|
||||
|
||||
lint-frontend:
|
||||
|
||||
@@ -48,7 +48,7 @@ module.exports = {
|
||||
// but not test __mocks__ directories (e.g., packages/superset-ui-core/test/__mocks/)
|
||||
'<rootDir>/packages/[^/]+/__mocks__',
|
||||
],
|
||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.jest.ts'],
|
||||
snapshotSerializers: ['@emotion/jest/serializer'],
|
||||
testEnvironmentOptions: {
|
||||
globalsCleanup: true,
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
"__webpack_public_path__": "writable",
|
||||
"__webpack_init_sharing__": "readonly",
|
||||
"__webpack_share_scopes__": "readonly",
|
||||
"jest": "readonly"
|
||||
"jest": "readonly",
|
||||
"vi": "readonly"
|
||||
},
|
||||
"settings": {
|
||||
"react": {
|
||||
|
||||
1897
superset-frontend/package-lock.json
generated
1897
superset-frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -81,9 +81,9 @@
|
||||
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006",
|
||||
"test-storybook": "test-storybook",
|
||||
"test-storybook:ci": "concurrently -k -s first -n \"SB,TEST\" -c \"magenta,blue\" \"npx http-server storybook-static --port 6006 --silent\" \"npx wait-on tcp:127.0.0.1:6006 && npm run test-storybook -- --maxWorkers=2\"",
|
||||
"tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --watch",
|
||||
"test": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80% --silent",
|
||||
"test-loud": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" jest --max-workers=80%",
|
||||
"tdd": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" vitest",
|
||||
"test": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" vitest --run --silent",
|
||||
"test-loud": "cross-env NODE_ENV=test NODE_OPTIONS=\"--max-old-space-size=8192\" vitest --run",
|
||||
"type": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192\" tsc --noEmit",
|
||||
"update-maps": "cd plugins/legacy-plugin-chart-country-map/scripts && jupyter nbconvert --to notebook --execute --inplace --allow-errors --ExecutePreprocessor.timeout=1200 'Country Map GeoJSON Generator.ipynb'",
|
||||
"validate-release": "../RELEASING/validate_this_release.sh"
|
||||
@@ -280,7 +280,6 @@
|
||||
"@testing-library/user-event": "^12.8.3",
|
||||
"@types/content-disposition": "^0.5.9",
|
||||
"@types/dom-to-image": "^2.6.7",
|
||||
"@types/jest": "^30.0.0",
|
||||
"@types/js-levenshtein": "^1.1.3",
|
||||
"@types/json-bigint": "^1.0.4",
|
||||
"@types/mousetrap": "^1.6.15",
|
||||
@@ -300,6 +299,8 @@
|
||||
"@types/unzipper": "^0.10.11",
|
||||
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
||||
"@typescript-eslint/parser": "^7.18.0",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"@vitest/coverage-v8": "^4.0.18",
|
||||
"babel-jest": "^30.0.2",
|
||||
"babel-loader": "^10.0.0",
|
||||
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||
@@ -337,7 +338,6 @@
|
||||
"imports-loader": "^5.0.0",
|
||||
"jest": "^30.3.0",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"jest-html-reporter": "^4.3.0",
|
||||
"jest-websocket-mock": "^2.5.0",
|
||||
"js-yaml-loader": "^1.2.2",
|
||||
"jsdom": "^28.1.0",
|
||||
@@ -366,6 +366,9 @@
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "5.4.5",
|
||||
"unzipper": "^0.12.3",
|
||||
"vite-plugin-svgr": "^4.5.0",
|
||||
"vite-tsconfig-paths": "^6.1.1",
|
||||
"vitest": "^4.0.18",
|
||||
"vm-browserify": "^1.1.2",
|
||||
"wait-on": "^9.0.4",
|
||||
"webpack": "^5.105.4",
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
"devDependencies": {
|
||||
"cross-env": "^10.1.0",
|
||||
"fs-extra": "^11.3.3",
|
||||
"jest": "^30.3.0",
|
||||
"yeoman-test": "^11.3.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -47,7 +47,7 @@ test('generator-superset:plugin-chart:creates files', async () => {
|
||||
result.assertFile([
|
||||
'.gitignore',
|
||||
'babel.config.js',
|
||||
'jest.config.js',
|
||||
'vi.config.js',
|
||||
'package.json',
|
||||
'README.md',
|
||||
'src/plugin/buildQuery.ts',
|
||||
|
||||
@@ -21,13 +21,13 @@ import { Theme } from './Theme';
|
||||
import { AnyThemeConfig, ThemeAlgorithm } from './types';
|
||||
|
||||
// Mock emotion's cache to avoid actual DOM operations
|
||||
jest.mock('@emotion/cache', () => ({
|
||||
vi.mock('@emotion/cache', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn().mockReturnValue({}),
|
||||
default: vi.fn().mockReturnValue({}),
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('Theme.json serializes the theme configuration to a JSON string', () => {
|
||||
|
||||
@@ -31,16 +31,16 @@ import { Theme } from '../Theme';
|
||||
import { ThemeAlgorithm } from '../types';
|
||||
|
||||
// Mock emotion's cache to avoid actual DOM operations
|
||||
jest.mock('@emotion/cache', () => ({
|
||||
vi.mock('@emotion/cache', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn().mockReturnValue({}),
|
||||
default: vi.fn().mockReturnValue({}),
|
||||
}));
|
||||
|
||||
let lightTheme: Theme;
|
||||
let darkTheme: Theme;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Create actual theme instances for testing
|
||||
lightTheme = Theme.fromConfig({
|
||||
|
||||
@@ -17,33 +17,33 @@
|
||||
* under the License.
|
||||
*/
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
jest.resetAllMocks();
|
||||
vi.resetModules();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
test('should pipe to `console` methods', () => {
|
||||
const { logging } = require('@apache-superset/core/utils');
|
||||
|
||||
jest.spyOn(logging, 'debug').mockImplementation();
|
||||
jest.spyOn(logging, 'log').mockImplementation();
|
||||
jest.spyOn(logging, 'info').mockImplementation();
|
||||
vi.spyOn(logging, 'debug').mockImplementation(() => {});
|
||||
vi.spyOn(logging, 'log').mockImplementation(() => {});
|
||||
vi.spyOn(logging, 'info').mockImplementation(() => {});
|
||||
expect(() => {
|
||||
logging.debug();
|
||||
logging.log();
|
||||
logging.info();
|
||||
}).not.toThrow();
|
||||
|
||||
jest.spyOn(logging, 'warn').mockImplementation(() => {
|
||||
vi.spyOn(logging, 'warn').mockImplementation(() => {
|
||||
throw new Error('warn');
|
||||
});
|
||||
expect(() => logging.warn()).toThrow('warn');
|
||||
|
||||
jest.spyOn(logging, 'error').mockImplementation(() => {
|
||||
vi.spyOn(logging, 'error').mockImplementation(() => {
|
||||
throw new Error('error');
|
||||
});
|
||||
expect(() => logging.error()).toThrow('error');
|
||||
|
||||
jest.spyOn(logging, 'trace').mockImplementation(() => {
|
||||
vi.spyOn(logging, 'trace').mockImplementation(() => {
|
||||
throw new Error('Trace:');
|
||||
});
|
||||
expect(() => logging.trace()).toThrow('Trace:');
|
||||
|
||||
@@ -21,10 +21,10 @@ import { render } from '@superset-ui/core/spec';
|
||||
import { GenericDataType } from '@apache-superset/core/common';
|
||||
import { ColumnOption, ColumnOptionProps } from '../../src';
|
||||
|
||||
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||
vi.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||
SQLPopover: () => <div data-test="mock-sql-popover" />,
|
||||
}));
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel',
|
||||
() => ({
|
||||
ColumnTypeLabel: ({ type }: { type: string }) => (
|
||||
@@ -33,7 +33,7 @@ jest.mock(
|
||||
}),
|
||||
);
|
||||
|
||||
jest.mock('@superset-ui/core/components/InfoTooltip', () => ({
|
||||
vi.mock('@superset-ui/core/components/InfoTooltip', () => ({
|
||||
InfoTooltip: () => <div data-test="mock-tooltip" />,
|
||||
}));
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import '@testing-library/jest-dom';
|
||||
import { fireEvent, render } from '@superset-ui/core/spec';
|
||||
import { InfoTooltip, InfoTooltipProps } from '@superset-ui/core/components';
|
||||
|
||||
jest.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
vi.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
Tooltip: ({ children }: { children: React.ReactNode }) => (
|
||||
<div data-test="mock-tooltip">{children}</div>
|
||||
),
|
||||
@@ -40,7 +40,7 @@ test('renders a tooltip', () => {
|
||||
});
|
||||
|
||||
test('responds to keydown events', () => {
|
||||
const clickHandler = jest.fn();
|
||||
const clickHandler = vi.fn();
|
||||
const { getByRole } = setup({
|
||||
label: 'test',
|
||||
tooltip: 'this is a test',
|
||||
|
||||
@@ -23,24 +23,24 @@ import {
|
||||
MetricOptionProps,
|
||||
} from '../../src/components/MetricOption';
|
||||
|
||||
jest.mock('@superset-ui/core/components/InfoTooltip', () => ({
|
||||
vi.mock('@superset-ui/core/components/InfoTooltip', () => ({
|
||||
InfoTooltip: () => <div data-test="mock-tooltip" />,
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'@superset-ui/chart-controls/components/ColumnTypeLabel/ColumnTypeLabel',
|
||||
() => ({
|
||||
ColumnTypeLabel: () => <div data-test="mock-column-type-label" />,
|
||||
}),
|
||||
);
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'@superset-ui/core/components/Tooltip',
|
||||
() =>
|
||||
({ children }: { children: React.ReactNode }) => (
|
||||
<div data-test="mock-tooltip">{children}</div>
|
||||
),
|
||||
);
|
||||
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||
vi.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||
SQLPopover: () => <div data-test="mock-sql-popover" />,
|
||||
}));
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ const defaultProps: RadioButtonControlProps = {
|
||||
['option2', 'Option 2'],
|
||||
['option3', 'Option 3'],
|
||||
],
|
||||
onChange: jest.fn(),
|
||||
onChange: vi.fn(),
|
||||
};
|
||||
|
||||
const setup = (props: Partial<RadioButtonControlProps> = {}) =>
|
||||
@@ -89,7 +89,7 @@ test('respects initial value prop', () => {
|
||||
});
|
||||
|
||||
test('calls onChange when radio button is clicked', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
setup({ onChange });
|
||||
|
||||
const secondOption = screen.getByText('Option 2');
|
||||
@@ -100,7 +100,7 @@ test('calls onChange when radio button is clicked', () => {
|
||||
});
|
||||
|
||||
test('handles multiple clicks correctly', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
setup({ onChange });
|
||||
|
||||
fireEvent.click(screen.getByText('Option 2'));
|
||||
@@ -130,7 +130,7 @@ test('disables specific options when disabled flag is set', () => {
|
||||
});
|
||||
|
||||
test('disabled options do not trigger onChange when clicked', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const optionsWithDisabled: RadioButtonOption[] = [
|
||||
{ value: 'opt1', label: 'Enabled' },
|
||||
{ value: 'opt2', label: 'Disabled', disabled: true },
|
||||
@@ -240,7 +240,7 @@ test('focuses button when clicked', () => {
|
||||
});
|
||||
|
||||
test('handles numeric values in options', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const numericOptions: RadioButtonOption[] = [
|
||||
[1, 'One'],
|
||||
[2, 'Two'],
|
||||
@@ -254,7 +254,7 @@ test('handles numeric values in options', () => {
|
||||
});
|
||||
|
||||
test('handles boolean values in options', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const booleanOptions: RadioButtonOption[] = [
|
||||
[true, 'True'],
|
||||
[false, 'False'],
|
||||
@@ -267,7 +267,7 @@ test('handles boolean values in options', () => {
|
||||
});
|
||||
|
||||
test('handles null values in options', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const nullOptions: RadioButtonOption[] = [
|
||||
[null, 'None'],
|
||||
['value', 'Value'],
|
||||
@@ -310,7 +310,7 @@ test('does not set aria-selected to true for unselected buttons', () => {
|
||||
});
|
||||
|
||||
test('backward compatibility with legacy array format', () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
const legacyOptions: RadioButtonOption[] = [
|
||||
['val1', 'Label 1'],
|
||||
['val2', 'Label 2'],
|
||||
@@ -327,7 +327,7 @@ test('backward compatibility with legacy array format', () => {
|
||||
|
||||
test('normalizeOption handles array format correctly', () => {
|
||||
const arrayOption: RadioButtonOption = ['value', 'Label'];
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
|
||||
setup({ options: [arrayOption], onChange });
|
||||
|
||||
@@ -343,7 +343,7 @@ test('normalizeOption handles object format correctly', () => {
|
||||
label: 'Label',
|
||||
disabled: false,
|
||||
};
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
|
||||
setup({ options: [objectOption], onChange });
|
||||
|
||||
|
||||
@@ -22,14 +22,14 @@ import { xAxisForceCategoricalControl } from '../../src/shared-controls/customCo
|
||||
import { checkColumnType } from '../../src/utils/checkColumnType';
|
||||
import type { ControlState } from '@superset-ui/chart-controls';
|
||||
|
||||
jest.mock('../../src/utils/checkColumnType');
|
||||
jest.mock('@superset-ui/core', () => ({
|
||||
...jest.requireActual('@superset-ui/core'),
|
||||
getColumnLabel: jest.fn((col: any) => col),
|
||||
vi.mock('../../src/utils/checkColumnType');
|
||||
vi.mock('@superset-ui/core', async importActual => ({
|
||||
...(await importActual()),
|
||||
getColumnLabel: vi.fn((col: any) => col),
|
||||
}));
|
||||
|
||||
test('xAxisForceCategoricalControl should not treat temporal columns as categorical when x_axis_sort exists', () => {
|
||||
const mockCheckColumnType = jest.mocked(checkColumnType);
|
||||
const mockCheckColumnType = vi.mocked(checkColumnType);
|
||||
|
||||
mockCheckColumnType.mockReturnValue(false); // temporal column (not numeric)
|
||||
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
import { ControlPanelState } from '../../src/types';
|
||||
|
||||
// Mock the utilities to avoid complex dependencies
|
||||
jest.mock('../../src/utils', () => ({
|
||||
formatSelectOptions: jest.fn((options: any[]) =>
|
||||
vi.mock('../../src/utils', () => ({
|
||||
formatSelectOptions: vi.fn((options: any[]) =>
|
||||
options.map((opt: any) => [opt, opt]),
|
||||
),
|
||||
displayTimeRelatedControls: jest.fn(() => true),
|
||||
getColorControlsProps: jest.fn(() => ({})),
|
||||
displayTimeRelatedControls: vi.fn(() => true),
|
||||
getColorControlsProps: vi.fn(() => ({})),
|
||||
D3_FORMAT_OPTIONS: [],
|
||||
D3_FORMAT_DOCS: '',
|
||||
D3_TIME_FORMAT_OPTIONS: [],
|
||||
|
||||
@@ -21,7 +21,7 @@ import { displayTimeRelatedControls } from '../../src';
|
||||
|
||||
const mockData = {
|
||||
actions: {
|
||||
setDatasource: jest.fn(),
|
||||
setDatasource: vi.fn(),
|
||||
},
|
||||
controls: {
|
||||
x_axis: {
|
||||
|
||||
@@ -83,7 +83,6 @@
|
||||
"@types/rison": "0.1.0",
|
||||
"@types/seedrandom": "^3.0.8",
|
||||
"fetch-mock": "^12.6.0",
|
||||
"jest-mock-console": "^2.0.0",
|
||||
"resize-observer-polyfill": "1.5.1",
|
||||
"timezone-mock": "1.4.0"
|
||||
},
|
||||
|
||||
@@ -24,7 +24,7 @@ import MatrixifyGridCell from './MatrixifyGridCell';
|
||||
import { MatrixifyGridCell as MatrixifyGridCellType } from '../../types/matrixify';
|
||||
|
||||
// Mock StatefulChart component
|
||||
jest.mock('../StatefulChart', () => {
|
||||
vi.mock('../StatefulChart', () => {
|
||||
/* eslint-disable no-restricted-syntax, global-require, @typescript-eslint/no-var-requires */
|
||||
const React = require('react');
|
||||
/* eslint-enable no-restricted-syntax, global-require, @typescript-eslint/no-var-requires */
|
||||
|
||||
@@ -23,21 +23,22 @@ import { ThemeProvider } from '@apache-superset/core/theme';
|
||||
import { supersetTheme } from '@apache-superset/core/theme';
|
||||
import MatrixifyGridRenderer from './MatrixifyGridRenderer';
|
||||
import { generateMatrixifyGrid } from './MatrixifyGridGenerator';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
// Mock the MatrixifyGridGenerator
|
||||
jest.mock('./MatrixifyGridGenerator', () => ({
|
||||
generateMatrixifyGrid: jest.fn(),
|
||||
vi.mock('./MatrixifyGridGenerator', () => ({
|
||||
generateMatrixifyGrid: vi.fn(),
|
||||
}));
|
||||
|
||||
// Mock MatrixifyGridCell component
|
||||
jest.mock('./MatrixifyGridCell', () =>
|
||||
vi.mock('./MatrixifyGridCell', () =>
|
||||
// eslint-disable-next-line react/display-name, @typescript-eslint/no-unused-vars
|
||||
({ cell, rowHeight, datasource, hooks }: any) => (
|
||||
<div data-testid={`grid-cell-${cell.id}`}>Cell: {cell.id}</div>
|
||||
),
|
||||
);
|
||||
|
||||
const mockGenerateMatrixifyGrid = generateMatrixifyGrid as jest.MockedFunction<
|
||||
const mockGenerateMatrixifyGrid = generateMatrixifyGrid as Mock<
|
||||
typeof generateMatrixifyGrid
|
||||
>;
|
||||
|
||||
@@ -45,7 +46,7 @@ const renderWithTheme = (component: React.ReactElement) =>
|
||||
render(<ThemeProvider theme={supersetTheme}>{component}</ThemeProvider>);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should create single group when fitting columns dynamically', () => {
|
||||
|
||||
@@ -28,13 +28,13 @@ import getChartBuildQueryRegistry from '../registries/ChartBuildQueryRegistrySin
|
||||
configure({ testIdAttribute: 'data-test' });
|
||||
|
||||
// Mock the registries
|
||||
jest.mock('../registries/ChartControlPanelRegistrySingleton');
|
||||
jest.mock('../registries/ChartMetadataRegistrySingleton');
|
||||
jest.mock('../registries/ChartBuildQueryRegistrySingleton');
|
||||
jest.mock('../clients/ChartClient');
|
||||
vi.mock('../registries/ChartControlPanelRegistrySingleton');
|
||||
vi.mock('../registries/ChartMetadataRegistrySingleton');
|
||||
vi.mock('../registries/ChartBuildQueryRegistrySingleton');
|
||||
vi.mock('../clients/ChartClient');
|
||||
|
||||
// Mock SuperChart component
|
||||
jest.mock('./SuperChart', () => ({
|
||||
vi.mock('./SuperChart', () => ({
|
||||
__esModule: true,
|
||||
// eslint-disable-next-line react/display-name
|
||||
default: ({ formData }: any) => (
|
||||
@@ -43,18 +43,18 @@ jest.mock('./SuperChart', () => ({
|
||||
}));
|
||||
|
||||
// Mock Loading component
|
||||
jest.mock('../../components/Loading', () => ({
|
||||
vi.mock('../../components/Loading', () => ({
|
||||
// eslint-disable-next-line react/display-name
|
||||
Loading: () => <div data-test="loading">Loading...</div>,
|
||||
}));
|
||||
|
||||
const mockChartClient = {
|
||||
client: {
|
||||
post: jest.fn().mockResolvedValue({
|
||||
post: vi.fn().mockResolvedValue({
|
||||
json: [{ data: 'test data' }],
|
||||
}),
|
||||
},
|
||||
loadFormData: jest.fn(),
|
||||
loadFormData: vi.fn(),
|
||||
};
|
||||
|
||||
const mockFormData = {
|
||||
@@ -64,21 +64,21 @@ const mockFormData = {
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
|
||||
// Setup default registry mocks
|
||||
(getChartMetadataRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue({
|
||||
get: vi.fn().mockReturnValue({
|
||||
useLegacyApi: false,
|
||||
}),
|
||||
});
|
||||
|
||||
(getChartBuildQueryRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockResolvedValue(null),
|
||||
get: vi.fn().mockResolvedValue(null),
|
||||
});
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(null),
|
||||
get: vi.fn().mockReturnValue(null),
|
||||
});
|
||||
|
||||
// Mock ChartClient constructor
|
||||
@@ -114,7 +114,7 @@ test('should refetch data when non-renderTrigger control changes', async () => {
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
@@ -166,7 +166,7 @@ test('should NOT refetch data when only renderTrigger controls change', async ()
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender, getByTestId } = render(
|
||||
@@ -202,7 +202,7 @@ test('should NOT refetch data when only renderTrigger controls change', async ()
|
||||
test('should refetch when control panel config is not available', async () => {
|
||||
// No control panel config available
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(null),
|
||||
get: vi.fn().mockReturnValue(null),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
@@ -246,7 +246,7 @@ test('should refetch when viz_type changes', async () => {
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
@@ -300,7 +300,7 @@ test('should handle mixed renderTrigger and non-renderTrigger changes', async ()
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
@@ -353,7 +353,7 @@ test('should handle controls with complex structure', async () => {
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender, getByTestId } = render(
|
||||
@@ -405,7 +405,7 @@ test('should not refetch when formData has not changed', async () => {
|
||||
test('should handle errors gracefully when accessing registry', async () => {
|
||||
// Mock registry to throw an error
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockImplementation(() => {
|
||||
get: vi.fn().mockImplementation(() => {
|
||||
throw new Error('Registry error');
|
||||
}),
|
||||
});
|
||||
@@ -493,7 +493,7 @@ test('should NOT refetch data when string-based renderTrigger control (zoomable)
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const formDataWithZoom = {
|
||||
@@ -543,7 +543,7 @@ test('should NOT refetch data when other string-based renderTrigger controls cha
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender, getByTestId } = render(
|
||||
@@ -586,7 +586,7 @@ test('should refetch when string control is NOT in RENDER_TRIGGER_SHARED_CONTROL
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const { rerender } = render(
|
||||
@@ -632,7 +632,7 @@ test('should handle mixed string and object controls correctly', async () => {
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const formDataWithControls = {
|
||||
@@ -688,7 +688,7 @@ test('should refetch when mixing renderTrigger string control with non-renderTri
|
||||
};
|
||||
|
||||
(getChartControlPanelRegistry as any).mockReturnValue({
|
||||
get: jest.fn().mockReturnValue(controlPanelConfig),
|
||||
get: vi.fn().mockReturnValue(controlPanelConfig),
|
||||
});
|
||||
|
||||
const formDataWithZoom = {
|
||||
@@ -729,7 +729,7 @@ test('should display error message when HTTP request fails with Response object'
|
||||
});
|
||||
mockChartClient.client.post.mockRejectedValue(mockResponse);
|
||||
|
||||
const onError = jest.fn();
|
||||
const onError = vi.fn();
|
||||
const { findByText } = render(
|
||||
<StatefulChart
|
||||
formData={mockFormData}
|
||||
|
||||
@@ -55,9 +55,9 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
test('should return the result from cache unless transformProps has changed', async () => {
|
||||
const pre = jest.fn(x => x);
|
||||
const transform = jest.fn(x => x);
|
||||
const post = jest.fn(x => x);
|
||||
const pre = vi.fn(x => x);
|
||||
const transform = vi.fn(x => x);
|
||||
const post = vi.fn(x => x);
|
||||
expect(getChartComponentRegistry().get(props.chartType)).toBe(FakeChart);
|
||||
|
||||
expect(pre).toHaveBeenCalledTimes(0);
|
||||
@@ -74,7 +74,7 @@ test('should return the result from cache unless transformProps has changed', as
|
||||
expect(transform).toHaveBeenCalledTimes(1);
|
||||
expect(post).toHaveBeenCalledTimes(1);
|
||||
|
||||
const updatedPost = jest.fn(x => x);
|
||||
const updatedPost = vi.fn(x => x);
|
||||
|
||||
rerender(
|
||||
<SuperChartCore
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
export const isMatrixifyEnabled = jest.fn(() => false);
|
||||
export const isMatrixifyEnabled = vi.fn(() => false);
|
||||
|
||||
export const MatrixifyGridRenderer = jest.fn(() => null);
|
||||
export const MatrixifyGridRenderer = vi.fn(() => null);
|
||||
|
||||
@@ -23,7 +23,7 @@ import { ActionButton } from '.';
|
||||
const defaultProps = {
|
||||
label: 'test-action',
|
||||
icon: <Icons.EditOutlined />,
|
||||
onClick: jest.fn(),
|
||||
onClick: vi.fn(),
|
||||
};
|
||||
|
||||
test('renders action button with icon', () => {
|
||||
@@ -36,7 +36,7 @@ test('renders action button with icon', () => {
|
||||
});
|
||||
|
||||
test('calls onClick when clicked', async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
render(<ActionButton {...defaultProps} onClick={onClick} />);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
|
||||
@@ -307,7 +307,7 @@ test('cleans up event listeners on unmount', async () => {
|
||||
if (!editorInstance) return;
|
||||
|
||||
// Spy on the commands.off method
|
||||
const offSpy = jest.spyOn(editorInstance.commands, 'off');
|
||||
const offSpy = vi.spyOn(editorInstance.commands, 'off');
|
||||
|
||||
// Unmount the component
|
||||
unmount();
|
||||
@@ -339,7 +339,7 @@ test('does not move autocomplete popup if target container is document.body', as
|
||||
// Mock the closest method to return null (simulating no #ace-editor parent)
|
||||
const originalClosest = editorInstance.container?.closest;
|
||||
if (editorInstance.container) {
|
||||
editorInstance.container.closest = jest.fn(() => null);
|
||||
editorInstance.container.closest = vi.fn(() => null);
|
||||
}
|
||||
|
||||
// Mock parentElement to be document.body
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('useJsonValidation', () => {
|
||||
});
|
||||
|
||||
test('falls back to "syntax error" when thrown error has no message (line 59 || branch)', () => {
|
||||
const spy = jest.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
||||
const spy = vi.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
||||
throw {}; // no .message property → error.message is undefined → falsy
|
||||
});
|
||||
|
||||
@@ -86,7 +86,7 @@ describe('useJsonValidation', () => {
|
||||
});
|
||||
|
||||
test('extracts row and column from error when message contains (line X column Y)', () => {
|
||||
const spy = jest.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
||||
const spy = vi.spyOn(JSON, 'parse').mockImplementationOnce(() => {
|
||||
throw new SyntaxError('Unexpected token (line 3 column 5)');
|
||||
});
|
||||
|
||||
|
||||
@@ -25,14 +25,14 @@ import {
|
||||
} from './Button.stories';
|
||||
|
||||
test('works with an onClick handler', () => {
|
||||
const mockAction = jest.fn();
|
||||
const mockAction = vi.fn();
|
||||
const { getByRole } = render(<Button onClick={mockAction} />);
|
||||
fireEvent.click(getByRole('button'));
|
||||
expect(mockAction).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('does not handle onClicks when disabled', () => {
|
||||
const mockAction = jest.fn();
|
||||
const mockAction = vi.fn();
|
||||
const { getByRole } = render(<Button onClick={mockAction} disabled />);
|
||||
fireEvent.click(getByRole('button'));
|
||||
expect(mockAction).toHaveBeenCalledTimes(0);
|
||||
|
||||
@@ -23,7 +23,7 @@ import type { CheckboxProps } from './types';
|
||||
const mockedProps: CheckboxProps = {
|
||||
checked: false,
|
||||
id: 'checkbox-id',
|
||||
onChange: jest.fn(),
|
||||
onChange: vi.fn(),
|
||||
disabled: false,
|
||||
title: 'Checkbox title',
|
||||
indeterminate: false,
|
||||
@@ -35,7 +35,7 @@ describe('Checkbox Component', () => {
|
||||
waitFor(() => render(<Checkbox {...props} />));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Rendering', () => {
|
||||
@@ -93,7 +93,7 @@ describe('Checkbox Component', () => {
|
||||
});
|
||||
|
||||
test('should not call the onChange handler when disabled and clicked', async () => {
|
||||
const mockOnChange = jest.fn();
|
||||
const mockOnChange = vi.fn();
|
||||
const disabledProps = {
|
||||
...mockedProps,
|
||||
disabled: true,
|
||||
@@ -109,7 +109,7 @@ describe('Checkbox Component', () => {
|
||||
});
|
||||
|
||||
test('calls onChange handler successfully', async () => {
|
||||
const mockAction = jest.fn();
|
||||
const mockAction = vi.fn();
|
||||
render(<Checkbox checked={false} onChange={mockAction} />);
|
||||
const checkboxInput = screen.getByRole('checkbox');
|
||||
await userEvent.click(checkboxInput);
|
||||
|
||||
@@ -20,7 +20,7 @@ import { render, screen } from '../../spec';
|
||||
import CodeSyntaxHighlighter from './index';
|
||||
|
||||
// Simple mock that just returns the content
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/light',
|
||||
() =>
|
||||
function MockSyntaxHighlighter({ children, ...props }: any) {
|
||||
@@ -33,26 +33,26 @@ jest.mock(
|
||||
);
|
||||
|
||||
// Mock the language modules
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/languages/hljs/sql',
|
||||
() => 'sql-mock',
|
||||
);
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/languages/hljs/json',
|
||||
() => 'json-mock',
|
||||
);
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/languages/hljs/htmlbars',
|
||||
() => 'html-mock',
|
||||
);
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/languages/hljs/markdown',
|
||||
() => 'md-mock',
|
||||
);
|
||||
|
||||
// Mock the styles
|
||||
jest.mock('react-syntax-highlighter/dist/cjs/styles/hljs/github', () => ({}));
|
||||
jest.mock(
|
||||
vi.mock('react-syntax-highlighter/dist/cjs/styles/hljs/github', () => ({}));
|
||||
vi.mock(
|
||||
'react-syntax-highlighter/dist/cjs/styles/hljs/atom-one-dark',
|
||||
() => ({}),
|
||||
);
|
||||
|
||||
@@ -22,8 +22,8 @@ import { ConfirmModal } from '.';
|
||||
|
||||
const defaultProps = {
|
||||
show: true,
|
||||
onHide: jest.fn(),
|
||||
onConfirm: jest.fn(),
|
||||
onHide: vi.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
title: 'Confirm Action',
|
||||
body: 'Are you sure you want to proceed?',
|
||||
};
|
||||
@@ -57,7 +57,7 @@ test('renders custom button text', () => {
|
||||
});
|
||||
|
||||
test('calls onConfirm when confirm button is clicked', () => {
|
||||
const onConfirm = jest.fn();
|
||||
const onConfirm = vi.fn();
|
||||
renderWithTheme(<ConfirmModal {...defaultProps} onConfirm={onConfirm} />);
|
||||
|
||||
userEvent.click(screen.getByRole('button', { name: 'Confirm' }));
|
||||
@@ -66,7 +66,7 @@ test('calls onConfirm when confirm button is clicked', () => {
|
||||
});
|
||||
|
||||
test('calls onHide when cancel button is clicked', () => {
|
||||
const onHide = jest.fn();
|
||||
const onHide = vi.fn();
|
||||
renderWithTheme(<ConfirmModal {...defaultProps} onHide={onHide} />);
|
||||
|
||||
userEvent.click(screen.getByRole('button', { name: 'Cancel' }));
|
||||
|
||||
@@ -24,11 +24,11 @@ import type { ConfirmStatusChangeProps } from './types';
|
||||
const mockedProps: Omit<ConfirmStatusChangeProps, 'children'> = {
|
||||
title: 'please confirm',
|
||||
description: 'are you sure?',
|
||||
onConfirm: jest.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
};
|
||||
|
||||
test('renders children with showConfirm function', () => {
|
||||
const childrenSpy = jest.fn().mockReturnValue(<div>test content</div>);
|
||||
const childrenSpy = vi.fn().mockReturnValue(<div>test content</div>);
|
||||
|
||||
render(
|
||||
<ConfirmStatusChange {...mockedProps}>{childrenSpy}</ConfirmStatusChange>,
|
||||
@@ -73,8 +73,8 @@ test('stores and passes arguments to onConfirm callback', async () => {
|
||||
|
||||
test('calls preventDefault on event-like arguments', () => {
|
||||
const mockEvent = {
|
||||
preventDefault: jest.fn(),
|
||||
stopPropagation: jest.fn(),
|
||||
preventDefault: vi.fn(),
|
||||
stopPropagation: vi.fn(),
|
||||
};
|
||||
|
||||
const { getByTestId } = render(
|
||||
@@ -93,7 +93,7 @@ test('calls preventDefault on event-like arguments', () => {
|
||||
|
||||
test('skips event handling on non-event arguments', () => {
|
||||
const regularArg = { someData: 'value' };
|
||||
const mockFunc = jest.fn();
|
||||
const mockFunc = vi.fn();
|
||||
|
||||
const { getByTestId } = render(
|
||||
<ConfirmStatusChange {...mockedProps}>
|
||||
@@ -134,8 +134,8 @@ test('ignores null and undefined arguments', () => {
|
||||
});
|
||||
|
||||
test('handles partial event objects gracefully', () => {
|
||||
const partialEvent1 = { preventDefault: jest.fn() }; // Only preventDefault
|
||||
const partialEvent2 = { stopPropagation: jest.fn() }; // Only stopPropagation
|
||||
const partialEvent1 = { preventDefault: vi.fn() }; // Only preventDefault
|
||||
const partialEvent2 = { stopPropagation: vi.fn() }; // Only stopPropagation
|
||||
|
||||
const { getByTestId } = render(
|
||||
<ConfirmStatusChange {...mockedProps}>
|
||||
|
||||
@@ -21,7 +21,7 @@ import { render } from '@superset-ui/core/spec';
|
||||
import * as ReactCronPicker from 'react-js-cron';
|
||||
import { CronPicker } from '.';
|
||||
|
||||
const spy = jest.spyOn(ReactCronPicker, 'default');
|
||||
const spy = vi.spyOn(ReactCronPicker, 'default');
|
||||
|
||||
test('Should send correct props to ReactCronPicker', () => {
|
||||
const props = {
|
||||
|
||||
@@ -23,8 +23,8 @@ test('Must display title and content', () => {
|
||||
const props = {
|
||||
title: <div data-test="test-title">Title</div>,
|
||||
description: <div data-test="test-description">Description</div>,
|
||||
onConfirm: jest.fn(),
|
||||
onHide: jest.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
onHide: vi.fn(),
|
||||
open: true,
|
||||
};
|
||||
render(<DeleteModal {...props} />);
|
||||
@@ -36,8 +36,8 @@ test('Input should autofocus when modal opens', async () => {
|
||||
const props = {
|
||||
title: <div data-test="test-title">Title</div>,
|
||||
description: <div data-test="test-description">Description</div>,
|
||||
onConfirm: jest.fn(),
|
||||
onHide: jest.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
onHide: vi.fn(),
|
||||
open: true,
|
||||
};
|
||||
render(<DeleteModal {...props} />);
|
||||
@@ -52,8 +52,8 @@ test('Calling "onHide"', async () => {
|
||||
const props = {
|
||||
title: <div data-test="test-title">Title</div>,
|
||||
description: <div data-test="test-description">Description</div>,
|
||||
onConfirm: jest.fn(),
|
||||
onHide: jest.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
onHide: vi.fn(),
|
||||
open: true,
|
||||
};
|
||||
const modal = <DeleteModal {...props} />;
|
||||
@@ -79,8 +79,8 @@ test('Calling "onConfirm" only after typing "delete" in the input', async () =>
|
||||
const props = {
|
||||
title: <div data-test="test-title">Title</div>,
|
||||
description: <div data-test="test-description">Description</div>,
|
||||
onConfirm: jest.fn(),
|
||||
onHide: jest.fn(),
|
||||
onConfirm: vi.fn(),
|
||||
onHide: vi.fn(),
|
||||
open: true,
|
||||
};
|
||||
render(<DeleteModal {...props} />);
|
||||
|
||||
@@ -41,7 +41,7 @@ describe('NoAnimationDropdown', () => {
|
||||
});
|
||||
|
||||
test('calls onBlur when it loses focus', () => {
|
||||
const onBlur = jest.fn();
|
||||
const onBlur = vi.fn();
|
||||
render(
|
||||
<NoAnimationDropdown {...props} onBlur={onBlur}>
|
||||
<button type="button">Test Button</button>
|
||||
@@ -52,7 +52,7 @@ describe('NoAnimationDropdown', () => {
|
||||
});
|
||||
|
||||
test('calls onKeyDown when a key is pressed', () => {
|
||||
const onKeyDown = jest.fn();
|
||||
const onKeyDown = vi.fn();
|
||||
render(
|
||||
<NoAnimationDropdown {...props} onKeyDown={onKeyDown}>
|
||||
<button type="button">Test Button</button>
|
||||
|
||||
@@ -29,13 +29,13 @@ const ITEMS = generateItems(10);
|
||||
|
||||
beforeEach(() => {
|
||||
// Reset any mocks
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
|
||||
// Mock ResizeObserver globally
|
||||
global.ResizeObserver = jest.fn().mockImplementation(() => ({
|
||||
observe: jest.fn(),
|
||||
unobserve: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
global.ResizeObserver = vi.fn().mockImplementation(() => ({
|
||||
observe: vi.fn(),
|
||||
unobserve: vi.fn(),
|
||||
disconnect: vi.fn(),
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -100,7 +100,7 @@ test('renders component with dropdown style prop without error', () => {
|
||||
});
|
||||
|
||||
test('renders component with onOverflowingStateChange prop without error', () => {
|
||||
const onOverflowingStateChange = jest.fn();
|
||||
const onOverflowingStateChange = vi.fn();
|
||||
render(
|
||||
<DropdownContainer
|
||||
items={generateItems(5)}
|
||||
@@ -160,7 +160,7 @@ test('accepts custom style props', () => {
|
||||
|
||||
// Integration test that doesn't rely on specific overflow behavior
|
||||
test('component renders and functions without throwing errors', () => {
|
||||
const onOverflowingStateChange = jest.fn();
|
||||
const onOverflowingStateChange = vi.fn();
|
||||
|
||||
expect(() => {
|
||||
render(
|
||||
|
||||
@@ -23,7 +23,7 @@ const createProps = (overrides: Record<string, any> = {}) => ({
|
||||
title: 'Chart title',
|
||||
placeholder: 'Add the name of the chart',
|
||||
canEdit: true,
|
||||
onSave: jest.fn(),
|
||||
onSave: vi.fn(),
|
||||
label: 'Chart title',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ const mockEvent = {
|
||||
const mockProps = {
|
||||
title: 'my title',
|
||||
canEdit: true,
|
||||
onSaveTitle: jest.fn(),
|
||||
onSaveTitle: vi.fn(),
|
||||
};
|
||||
|
||||
test('should render title', () => {
|
||||
@@ -40,7 +40,7 @@ test('should render title', () => {
|
||||
|
||||
test('should not render an input if it is not editable', () => {
|
||||
const { queryByTestId } = render(
|
||||
<EditableTitle title="my title" onSaveTitle={jest.fn()} />,
|
||||
<EditableTitle title="my title" onSaveTitle={vi.fn()} />,
|
||||
);
|
||||
expect(
|
||||
queryByTestId('textarea-editable-title-input'),
|
||||
@@ -75,7 +75,7 @@ describe('should handle blur', () => {
|
||||
};
|
||||
|
||||
test('should trigger callback', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
const { getByTestId } = setup({ onSaveTitle: callback });
|
||||
fireEvent.change(getByTestId('textarea-editable-title-input'), mockEvent);
|
||||
fireEvent.blur(getByTestId('textarea-editable-title-input'));
|
||||
@@ -84,7 +84,7 @@ describe('should handle blur', () => {
|
||||
});
|
||||
|
||||
test('should not trigger callback', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
const { getByTestId } = setup({ onSaveTitle: callback });
|
||||
fireEvent.blur(getByTestId('textarea-editable-title-input'));
|
||||
// no change
|
||||
@@ -92,7 +92,7 @@ describe('should handle blur', () => {
|
||||
});
|
||||
|
||||
test('should not save empty title', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
const { getByTestId } = setup({ onSaveTitle: callback });
|
||||
const textarea = getByTestId('textarea-editable-title-input');
|
||||
fireEvent.blur(textarea);
|
||||
|
||||
@@ -20,14 +20,14 @@
|
||||
import { render, screen, userEvent } from '@superset-ui/core/spec';
|
||||
import { FaveStar } from '.';
|
||||
|
||||
jest.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
vi.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
Tooltip: (props: any) => <div data-test="tooltip" {...props} />,
|
||||
}));
|
||||
|
||||
test('render right content', async () => {
|
||||
const props = {
|
||||
itemId: 3,
|
||||
saveFaveStar: jest.fn(),
|
||||
saveFaveStar: vi.fn(),
|
||||
};
|
||||
|
||||
const { rerender, findByRole } = render(<FaveStar {...props} isStarred />);
|
||||
@@ -52,7 +52,7 @@ test('render content on tooltip', async () => {
|
||||
const props = {
|
||||
itemId: 3,
|
||||
showTooltip: true,
|
||||
saveFaveStar: jest.fn(),
|
||||
saveFaveStar: vi.fn(),
|
||||
};
|
||||
|
||||
render(<FaveStar {...props} />);
|
||||
@@ -72,8 +72,8 @@ test('render content on tooltip', async () => {
|
||||
test('Call fetchFaveStar on first render and on itemId change', async () => {
|
||||
const props = {
|
||||
itemId: 3,
|
||||
fetchFaveStar: jest.fn(),
|
||||
saveFaveStar: jest.fn(),
|
||||
fetchFaveStar: vi.fn(),
|
||||
saveFaveStar: vi.fn(),
|
||||
isStarred: false,
|
||||
showTooltip: false,
|
||||
};
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('IconButton', () => {
|
||||
});
|
||||
|
||||
test('handles Enter and Space key presses', () => {
|
||||
const mockOnClick = jest.fn();
|
||||
const mockOnClick = vi.fn();
|
||||
render(<IconButton {...defaultProps} onClick={mockOnClick} />);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
@@ -79,7 +79,7 @@ describe('IconButton', () => {
|
||||
});
|
||||
|
||||
test('calls onClick handler when clicked', () => {
|
||||
const mockOnClick = jest.fn();
|
||||
const mockOnClick = vi.fn();
|
||||
render(<IconButton {...defaultProps} onClick={mockOnClick} />);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import { render } from '@superset-ui/core/spec';
|
||||
import { IconTooltip } from '.';
|
||||
|
||||
jest.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
vi.mock('@superset-ui/core/components/Tooltip', () => ({
|
||||
Tooltip: () => <div data-test="mock-tooltip" />,
|
||||
}));
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ test('renders the base component (no onClick)', () => {
|
||||
});
|
||||
|
||||
test('works with an onClick handler', () => {
|
||||
const mockAction = jest.fn();
|
||||
const mockAction = vi.fn();
|
||||
const { getByText } = render(<Label onClick={mockAction}>test</Label>);
|
||||
fireEvent.click(getByText('test'));
|
||||
expect(mockAction).toHaveBeenCalled();
|
||||
|
||||
@@ -28,7 +28,7 @@ test('renders the base component (no refresh)', () => {
|
||||
});
|
||||
|
||||
test('renders a refresh action', () => {
|
||||
const mockAction = jest.fn();
|
||||
const mockAction = vi.fn();
|
||||
render(<LastUpdated updatedAt={updatedAt} update={mockAction} />);
|
||||
|
||||
const button = screen.getByRole('button');
|
||||
|
||||
@@ -21,7 +21,7 @@ import fetchMock from 'fetch-mock';
|
||||
import { render, screen } from '@superset-ui/core/spec';
|
||||
import { ImageLoader, type BackgroundPosition } from './ImageLoader';
|
||||
|
||||
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
||||
global.URL.createObjectURL = vi.fn(() => '/local_url');
|
||||
const blob = new Blob([], { type: 'image/png' });
|
||||
|
||||
beforeAll(() => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import fetchMock from 'fetch-mock';
|
||||
import { render, screen } from '@superset-ui/core/spec';
|
||||
import { ListViewCard } from '.';
|
||||
|
||||
global.URL.createObjectURL = jest.fn(() => '/local_url');
|
||||
global.URL.createObjectURL = vi.fn(() => '/local_url');
|
||||
fetchMock.get('/thumbnail', { body: new Blob(), sendAsJson: false });
|
||||
|
||||
describe('ListViewCard', () => {
|
||||
|
||||
@@ -22,19 +22,19 @@ import * as themeModule from '@apache-superset/core/theme';
|
||||
import { Loading } from '.';
|
||||
|
||||
// Mock the loading SVG import since it's a file stub in tests
|
||||
jest.mock('../assets', () => ({
|
||||
vi.mock('../assets', () => ({
|
||||
Loading: () => <svg data-test="default-loading-svg" />,
|
||||
}));
|
||||
|
||||
const mockUseTheme = jest.fn();
|
||||
const mockUseTheme = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
mockUseTheme.mockReset();
|
||||
jest.spyOn(themeModule, 'useTheme').mockImplementation(mockUseTheme);
|
||||
vi.spyOn(themeModule, 'useTheme').mockImplementation(mockUseTheme);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('uses default spinner when no theme spinner configured', () => {
|
||||
|
||||
@@ -42,7 +42,7 @@ const A_WEEK_AGO = 'a week ago';
|
||||
const TWO_DAYS_AGO = '2 days ago';
|
||||
|
||||
const runWithBarCollapsed = async (func: Function) => {
|
||||
const spy = jest.spyOn(resizeDetector, 'useResizeDetector');
|
||||
const spy = vi.spyOn(resizeDetector, 'useResizeDetector');
|
||||
let width: number;
|
||||
spy.mockImplementation(props => {
|
||||
if (props?.onResize && !width) {
|
||||
@@ -101,7 +101,7 @@ test('renders an array of items', () => {
|
||||
});
|
||||
|
||||
test('throws errors when out of min/max restrictions', () => {
|
||||
const spy = jest.spyOn(console, 'error');
|
||||
const spy = vi.spyOn(console, 'error');
|
||||
spy.mockImplementation(() => {});
|
||||
expect(() =>
|
||||
render(<MetadataBar items={ITEMS.slice(0, MIN_NUMBER_ITEMS - 1)} />),
|
||||
@@ -148,7 +148,7 @@ test('renders a tooltip when one is provided even if not collapsed', async () =>
|
||||
});
|
||||
|
||||
test('renders underlined text and emits event when clickable', async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const items = [{ ...ITEMS[0], onClick }, ITEMS[1]];
|
||||
render(<MetadataBar items={items} />);
|
||||
const element = screen.getByText(DASHBOARD_TITLE);
|
||||
@@ -160,7 +160,7 @@ test('renders underlined text and emits event when clickable', async () => {
|
||||
|
||||
test('renders clickable items with blue icons when the bar is collapsed', async () => {
|
||||
await runWithBarCollapsed(async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const items = [{ ...ITEMS[0], onClick }, ITEMS[1]];
|
||||
render(<MetadataBar items={items} />);
|
||||
const images = screen.getAllByRole('img');
|
||||
@@ -266,7 +266,7 @@ test('correctly renders the tags tooltip', async () => {
|
||||
});
|
||||
|
||||
test('renders StyledItem with role="button" when onClick is defined', () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const items = [
|
||||
{ ...ITEMS[0], onClick },
|
||||
{ ...ITEMS[1], onClick },
|
||||
|
||||
@@ -47,10 +47,10 @@ describe('FormModal Component', () => {
|
||||
|
||||
const mockedProps: FormModalProps = {
|
||||
show: true,
|
||||
onHide: jest.fn(),
|
||||
onHide: vi.fn(),
|
||||
title: 'Test Form Modal',
|
||||
onSave: jest.fn(),
|
||||
formSubmitHandler: jest.fn().mockResolvedValue(undefined),
|
||||
onSave: vi.fn(),
|
||||
formSubmitHandler: vi.fn().mockResolvedValue(undefined),
|
||||
initialValues: { name: '', email: '' },
|
||||
requiredFields: ['name'],
|
||||
children,
|
||||
|
||||
@@ -25,14 +25,14 @@ const defaultProps: PageHeaderWithActionsProps = {
|
||||
editableTitleProps: {
|
||||
title: 'Test title',
|
||||
placeholder: 'Test placeholder',
|
||||
onSave: jest.fn(),
|
||||
onSave: vi.fn(),
|
||||
canEdit: true,
|
||||
label: 'Title',
|
||||
},
|
||||
showTitlePanelItems: true,
|
||||
certificatiedBadgeProps: {},
|
||||
showFaveStar: true,
|
||||
faveStarProps: { itemId: 1, saveFaveStar: jest.fn() },
|
||||
faveStarProps: { itemId: 1, saveFaveStar: vi.fn() },
|
||||
titlePanelAdditionalItems: <button type="button">Title panel button</button>,
|
||||
rightPanelAdditionalItems: <button type="button">Save</button>,
|
||||
additionalActionsMenu: (
|
||||
@@ -41,7 +41,7 @@ const defaultProps: PageHeaderWithActionsProps = {
|
||||
data-test="additional-actions-menu"
|
||||
/>
|
||||
),
|
||||
menuDropdownProps: { onVisibleChange: jest.fn(), visible: true },
|
||||
menuDropdownProps: { onVisibleChange: vi.fn(), visible: true },
|
||||
};
|
||||
|
||||
test('Renders', async () => {
|
||||
|
||||
@@ -58,7 +58,7 @@ test('renders with icon child', async () => {
|
||||
});
|
||||
|
||||
test('fires an event when visibility is changed', async () => {
|
||||
const onOpenChange = jest.fn();
|
||||
const onOpenChange = vi.fn();
|
||||
render(
|
||||
<Popover
|
||||
content="Content sample"
|
||||
|
||||
@@ -31,7 +31,7 @@ const defaultProps: PopoverDropdownProps = {
|
||||
value: '1',
|
||||
renderButton: (option: OptionProps) => <span>{option.label}</span>,
|
||||
renderOption: (option: OptionProps) => <div>{option.label}</div>,
|
||||
onChange: jest.fn(),
|
||||
onChange: vi.fn(),
|
||||
};
|
||||
|
||||
test('renders with default props', async () => {
|
||||
|
||||
@@ -49,7 +49,7 @@ test('renders a tooltip when hovered', async () => {
|
||||
});
|
||||
|
||||
test('calls onSelect when clicked', async () => {
|
||||
const onSelect = jest.fn();
|
||||
const onSelect = vi.fn();
|
||||
render(
|
||||
<PopoverSection title="Title" onSelect={onSelect}>
|
||||
<div role="form" />
|
||||
|
||||
@@ -20,7 +20,7 @@ import { render, screen, userEvent } from '@superset-ui/core/spec';
|
||||
import RefreshLabel from '@superset-ui/core/components/RefreshLabel';
|
||||
|
||||
test('renders with default props', async () => {
|
||||
render(<RefreshLabel tooltipContent="Tooltip" onClick={jest.fn()} />);
|
||||
render(<RefreshLabel tooltipContent="Tooltip" onClick={vi.fn()} />);
|
||||
const refresh = await screen.findByRole('button');
|
||||
expect(refresh).toBeInTheDocument();
|
||||
await userEvent.hover(refresh);
|
||||
@@ -28,7 +28,7 @@ test('renders with default props', async () => {
|
||||
|
||||
test('renders tooltip on hover', async () => {
|
||||
const tooltipText = 'Tooltip';
|
||||
render(<RefreshLabel tooltipContent={tooltipText} onClick={jest.fn()} />);
|
||||
render(<RefreshLabel tooltipContent={tooltipText} onClick={vi.fn()} />);
|
||||
const refresh = screen.getByRole('button');
|
||||
await userEvent.hover(refresh);
|
||||
const tooltip = await screen.findByRole('tooltip');
|
||||
@@ -37,7 +37,7 @@ test('renders tooltip on hover', async () => {
|
||||
});
|
||||
|
||||
test('triggers on click event', async () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
render(<RefreshLabel tooltipContent="Tooltip" onClick={onClick} />);
|
||||
const refresh = await screen.findByRole('button');
|
||||
await userEvent.click(refresh);
|
||||
|
||||
@@ -153,7 +153,7 @@ test('displays a header', async () => {
|
||||
});
|
||||
|
||||
test('adds a new option if the value is not in the options, when options are empty', async () => {
|
||||
const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
const loadOptions = vi.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
render(
|
||||
<AsyncSelect {...defaultProps} options={loadOptions} value={OPTIONS[0]} />,
|
||||
);
|
||||
@@ -167,7 +167,7 @@ test('adds a new option if the value is not in the options, when options are emp
|
||||
});
|
||||
|
||||
test('adds a new option if the value is not in the options, when options have values', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [OPTIONS[1]],
|
||||
totalCount: 1,
|
||||
}));
|
||||
@@ -185,7 +185,7 @@ test('adds a new option if the value is not in the options, when options have va
|
||||
});
|
||||
|
||||
test('does not add a new option if the value is already in the options', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [OPTIONS[0]],
|
||||
totalCount: 1,
|
||||
}));
|
||||
@@ -206,7 +206,7 @@ test('inverts the selection', async () => {
|
||||
});
|
||||
|
||||
test('sort the options by label if no sort comparator is provided', async () => {
|
||||
const loadUnsortedOptions = jest.fn(async () => ({
|
||||
const loadUnsortedOptions = vi.fn(async () => ({
|
||||
data: [...OPTIONS].sort(() => Math.random()),
|
||||
totalCount: 2,
|
||||
}));
|
||||
@@ -324,7 +324,7 @@ test('ignores case when searching', async () => {
|
||||
});
|
||||
|
||||
test('same case should be ranked to the top', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [
|
||||
{ value: 'Cac' },
|
||||
{ value: 'abac' },
|
||||
@@ -399,7 +399,7 @@ test('removes duplicated values', async () => {
|
||||
});
|
||||
|
||||
test('renders a custom label', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [
|
||||
{ value: 'John', label: <h1>John</h1> },
|
||||
{ value: 'Liam', label: <h1>Liam</h1> },
|
||||
@@ -415,7 +415,7 @@ test('renders a custom label', async () => {
|
||||
});
|
||||
|
||||
test('searches for a word with a custom label', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [
|
||||
{ value: 'John', label: <h1>John</h1> },
|
||||
{ value: 'Liam', label: <h1>Liam</h1> },
|
||||
@@ -441,7 +441,7 @@ test('removes a new option if the user does not select it', async () => {
|
||||
});
|
||||
|
||||
test('clear all the values', async () => {
|
||||
const onClear = jest.fn();
|
||||
const onClear = vi.fn();
|
||||
render(
|
||||
<AsyncSelect
|
||||
{...defaultProps}
|
||||
@@ -466,7 +466,7 @@ test('does not add a new option if allowNewOptions is false', async () => {
|
||||
});
|
||||
|
||||
test('adds the null option when selected in single mode', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [OPTIONS[0], NULL_OPTION],
|
||||
totalCount: 2,
|
||||
}));
|
||||
@@ -478,7 +478,7 @@ test('adds the null option when selected in single mode', async () => {
|
||||
});
|
||||
|
||||
test('adds the null option when selected in multiple mode', async () => {
|
||||
const loadOptions = jest.fn(async () => ({
|
||||
const loadOptions = vi.fn(async () => ({
|
||||
data: [OPTIONS[0], NULL_OPTION],
|
||||
totalCount: 2,
|
||||
}));
|
||||
@@ -541,7 +541,7 @@ test('multiple selections in multiple mode', async () => {
|
||||
});
|
||||
|
||||
test('changes the selected item in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<AsyncSelect {...defaultProps} onChange={onChange} />);
|
||||
await open();
|
||||
const [firstOption, secondOption] = OPTIONS;
|
||||
@@ -674,7 +674,7 @@ test('searches for matches in both loaded and unloaded pages', async () => {
|
||||
});
|
||||
|
||||
test('searches for an item in a page not loaded', async () => {
|
||||
const mock = jest.fn(loadOptions);
|
||||
const mock = vi.fn(loadOptions);
|
||||
render(<AsyncSelect {...defaultProps} options={mock} />);
|
||||
const search = 'Sandro';
|
||||
await open();
|
||||
@@ -686,20 +686,20 @@ test('searches for an item in a page not loaded', async () => {
|
||||
});
|
||||
|
||||
test('does not fetches data when rendering', async () => {
|
||||
const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
const loadOptions = vi.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
render(<AsyncSelect {...defaultProps} options={loadOptions} />);
|
||||
expect(loadOptions).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('fetches data when opening', async () => {
|
||||
const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
const loadOptions = vi.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
render(<AsyncSelect {...defaultProps} options={loadOptions} />);
|
||||
await open();
|
||||
expect(loadOptions).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('fetches data only after a search input is entered if fetchOnlyOnSearch is true', async () => {
|
||||
const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
const loadOptions = vi.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
render(
|
||||
<AsyncSelect {...defaultProps} options={loadOptions} fetchOnlyOnSearch />,
|
||||
);
|
||||
@@ -720,7 +720,7 @@ test('displays an error message when an exception is thrown while fetching', asy
|
||||
});
|
||||
|
||||
test('does not fire a new request for the same search input', async () => {
|
||||
const loadOptions = jest.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
const loadOptions = vi.fn(async () => ({ data: [], totalCount: 0 }));
|
||||
render(
|
||||
<AsyncSelect {...defaultProps} options={loadOptions} fetchOnlyOnSearch />,
|
||||
);
|
||||
@@ -731,7 +731,7 @@ test('does not fire a new request for the same search input', async () => {
|
||||
});
|
||||
|
||||
test('does not fire a new request if all values have been fetched', async () => {
|
||||
const mock = jest.fn(loadOptions);
|
||||
const mock = vi.fn(loadOptions);
|
||||
const search = 'George';
|
||||
const pageSize = OPTIONS.length;
|
||||
render(<AsyncSelect {...defaultProps} options={mock} pageSize={pageSize} />);
|
||||
@@ -743,7 +743,7 @@ test('does not fire a new request if all values have been fetched', async () =>
|
||||
});
|
||||
|
||||
test('fires a new request if all values have not been fetched', async () => {
|
||||
const mock = jest.fn(loadOptions);
|
||||
const mock = vi.fn(loadOptions);
|
||||
const pageSize = OPTIONS.length / 2;
|
||||
render(<AsyncSelect {...defaultProps} options={mock} pageSize={pageSize} />);
|
||||
await open();
|
||||
@@ -774,7 +774,7 @@ test('renders a helper text when one is provided', async () => {
|
||||
});
|
||||
|
||||
test('finds an element with a numeric value and does not duplicate the options', async () => {
|
||||
const options = jest.fn(async () => ({
|
||||
const options = vi.fn(async () => ({
|
||||
data: [
|
||||
{ label: 'a', value: 11 },
|
||||
{ label: 'b', value: 12 },
|
||||
@@ -837,7 +837,7 @@ test('Renders only an overflow tag if dropdown is open in oneLine mode', async (
|
||||
});
|
||||
|
||||
test('does not fire onChange when searching but no selection', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<div role="main">
|
||||
<AsyncSelect
|
||||
@@ -856,7 +856,7 @@ test('does not fire onChange when searching but no selection', async () => {
|
||||
});
|
||||
|
||||
test('fires onChange when clearing the selection in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<AsyncSelect
|
||||
{...defaultProps}
|
||||
@@ -870,7 +870,7 @@ test('fires onChange when clearing the selection in single mode', async () => {
|
||||
});
|
||||
|
||||
test('fires onChange when clearing the selection in multiple mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<AsyncSelect
|
||||
{...defaultProps}
|
||||
@@ -884,7 +884,7 @@ test('fires onChange when clearing the selection in multiple mode', async () =>
|
||||
});
|
||||
|
||||
test('fires onChange when pasting a selection', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<AsyncSelect {...defaultProps} onChange={onChange} />);
|
||||
await open();
|
||||
const input = getElementByClassName('.ant-select-selection-search-input');
|
||||
@@ -916,7 +916,7 @@ test('does not duplicate options when using numeric values', async () => {
|
||||
});
|
||||
|
||||
test('pasting an existing option does not duplicate it', async () => {
|
||||
const options = jest.fn(async () => ({
|
||||
const options = vi.fn(async () => ({
|
||||
data: [OPTIONS[0]],
|
||||
totalCount: 1,
|
||||
}));
|
||||
@@ -933,7 +933,7 @@ test('pasting an existing option does not duplicate it', async () => {
|
||||
});
|
||||
|
||||
test('pasting an existing option does not duplicate it in multiple mode', async () => {
|
||||
const options = jest.fn(async () => ({
|
||||
const options = vi.fn(async () => ({
|
||||
data: [
|
||||
{ label: 'John', value: 1 },
|
||||
{ label: 'Liam', value: 2 },
|
||||
@@ -983,7 +983,7 @@ test('pasting an non-existent option should not add it if allowNewOptions is fal
|
||||
});
|
||||
|
||||
test('onChange is called with the value property when pasting an option that was not loaded yet', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<AsyncSelect {...defaultProps} onChange={onChange} />);
|
||||
await open();
|
||||
const input = getElementByClassName('.ant-select-selection-search-input');
|
||||
@@ -1003,7 +1003,7 @@ test('onChange is called with the value property when pasting an option that was
|
||||
});
|
||||
|
||||
test('does not fire onChange if the same value is selected in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<AsyncSelect {...defaultProps} onChange={onChange} />);
|
||||
const optionText = 'Emma';
|
||||
await open();
|
||||
|
||||
@@ -412,7 +412,7 @@ test('removes a new option if the user does not select it', async () => {
|
||||
});
|
||||
|
||||
test('clear all the values', async () => {
|
||||
const onClear = jest.fn();
|
||||
const onClear = vi.fn();
|
||||
render(
|
||||
<Select
|
||||
{...defaultProps}
|
||||
@@ -493,7 +493,7 @@ test('multiple selections in multiple mode', async () => {
|
||||
});
|
||||
|
||||
test('changes the selected item in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<Select {...defaultProps} onChange={onChange} />);
|
||||
await open();
|
||||
const [firstOption, secondOption] = OPTIONS;
|
||||
@@ -602,7 +602,7 @@ test('searches for an item', async () => {
|
||||
});
|
||||
|
||||
test('triggers getPopupContainer if passed', async () => {
|
||||
const getPopupContainer = jest.fn();
|
||||
const getPopupContainer = vi.fn();
|
||||
render(<Select {...defaultProps} getPopupContainer={getPopupContainer} />);
|
||||
await open();
|
||||
expect(getPopupContainer).toHaveBeenCalled();
|
||||
@@ -916,7 +916,7 @@ test('"Select all" does not affect disabled options', async () => {
|
||||
});
|
||||
|
||||
test('does not fire onChange when searching but no selection', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<div role="main">
|
||||
<Select
|
||||
@@ -935,7 +935,7 @@ test('does not fire onChange when searching but no selection', async () => {
|
||||
});
|
||||
|
||||
test('fires onChange when clearing the selection in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<Select
|
||||
{...defaultProps}
|
||||
@@ -949,7 +949,7 @@ test('fires onChange when clearing the selection in single mode', async () => {
|
||||
});
|
||||
|
||||
test('fires onChange when clearing the selection in multiple mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(
|
||||
<Select
|
||||
{...defaultProps}
|
||||
@@ -963,7 +963,7 @@ test('fires onChange when clearing the selection in multiple mode', async () =>
|
||||
});
|
||||
|
||||
test('fires onChange when pasting a selection', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<Select {...defaultProps} onChange={onChange} />);
|
||||
await open();
|
||||
const input = getElementByClassName('.ant-select-selection-search-input');
|
||||
@@ -1045,7 +1045,7 @@ test('pasting an non-existent option should not add it if allowNewOptions is fal
|
||||
});
|
||||
|
||||
test('does not fire onChange if the same value is selected in single mode', async () => {
|
||||
const onChange = jest.fn();
|
||||
const onChange = vi.fn();
|
||||
render(<Select {...defaultProps} onChange={onChange} />);
|
||||
const optionText = 'Emma';
|
||||
await open();
|
||||
@@ -1058,25 +1058,25 @@ test('does not fire onChange if the same value is selected in single mode', asyn
|
||||
|
||||
// Reference for the bug this tests: https://github.com/apache/superset/pull/33043#issuecomment-2809419640
|
||||
test('typing and deleting the last character for a new option displays correctly', async () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
render(<Select {...defaultProps} allowNewOptions />);
|
||||
|
||||
await open();
|
||||
await type('aaa', 0, false);
|
||||
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
|
||||
await type('{backspace}', 0, false);
|
||||
await type('a', 0, false);
|
||||
|
||||
jest.runAllTimers();
|
||||
vi.runAllTimers();
|
||||
|
||||
expect(
|
||||
screen.queryByText(NO_DATA, { selector: '.ant-empty-description' }),
|
||||
).not.toBeInTheDocument();
|
||||
expect(await findSelectOption('aaa')).toBeInTheDocument();
|
||||
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe('grouped options search', () => {
|
||||
|
||||
@@ -21,7 +21,7 @@ import ActionCell, { appendDataToMenu } from './index';
|
||||
import { exampleMenuOptions, exampleRow } from './fixtures';
|
||||
|
||||
test('renders with default props', async () => {
|
||||
const clickHandler = jest.fn();
|
||||
const clickHandler = vi.fn();
|
||||
exampleMenuOptions[0].onClick = clickHandler;
|
||||
render(<ActionCell menuOptions={exampleMenuOptions} row={exampleRow} />);
|
||||
// Open the menu
|
||||
|
||||
@@ -21,7 +21,7 @@ import ButtonCell from './index';
|
||||
import { exampleRow } from '../fixtures';
|
||||
|
||||
test('renders with default props', async () => {
|
||||
const clickHandler = jest.fn();
|
||||
const clickHandler = vi.fn();
|
||||
const BUTTON_LABEL = 'Button Label';
|
||||
|
||||
render(
|
||||
|
||||
@@ -45,7 +45,7 @@ afterEach(() => {
|
||||
|
||||
test('constructor initializes with correct defaults', () => {
|
||||
const table = createMockTable();
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -62,7 +62,7 @@ test('constructor initializes with correct defaults', () => {
|
||||
|
||||
test('setTableRef updates tableRef', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const newTable = createMockTable();
|
||||
utils.setTableRef(newTable);
|
||||
expect(utils.tableRef).toBe(newTable);
|
||||
@@ -70,14 +70,14 @@ test('setTableRef updates tableRef', () => {
|
||||
|
||||
test('getColumnIndex returns -1 when columnRef has no parent', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.columnRef = null;
|
||||
expect(utils.getColumnIndex()).toBe(-1);
|
||||
});
|
||||
|
||||
test('getColumnIndex returns correct index when columnRef is in a row', () => {
|
||||
const table = createMockTable(3);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const row = table.rows[0];
|
||||
utils.columnRef = row.cells[1] as unknown as typeof utils.columnRef;
|
||||
expect(utils.getColumnIndex()).toBe(1);
|
||||
@@ -85,15 +85,15 @@ test('getColumnIndex returns correct index when columnRef is in a row', () => {
|
||||
|
||||
test('allowDrop calls preventDefault on the event', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const event = { preventDefault: jest.fn() } as unknown as DragEvent;
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const event = { preventDefault: vi.fn() } as unknown as DragEvent;
|
||||
utils.allowDrop(event);
|
||||
expect(event.preventDefault).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('handleMouseup clears mouseDown and resets dragging state', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const th = document.createElement('th') as unknown as typeof utils.columnRef;
|
||||
utils.columnRef = th;
|
||||
(th as any).mouseDown = true;
|
||||
@@ -107,7 +107,7 @@ test('handleMouseup clears mouseDown and resets dragging state', () => {
|
||||
|
||||
test('handleMouseup works when columnRef is null', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.columnRef = null;
|
||||
utils.isDragging = true;
|
||||
|
||||
@@ -118,7 +118,7 @@ test('handleMouseup works when columnRef is null', () => {
|
||||
|
||||
test('handleMouseDown sets mouseDown and oldX when within resize range', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const target = document.createElement('th') as any;
|
||||
Object.defineProperty(target, 'offsetWidth', {
|
||||
value: 100,
|
||||
@@ -141,7 +141,7 @@ test('handleMouseDown sets mouseDown and oldX when within resize range', () => {
|
||||
|
||||
test('handleMouseDown sets draggable when outside resize range and reorderable', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.reorderable = true;
|
||||
|
||||
const target = document.createElement('th') as any;
|
||||
@@ -163,9 +163,9 @@ test('handleMouseDown sets draggable when outside resize range and reorderable',
|
||||
|
||||
test('initializeResizableColumns adds event listeners when resizable is true', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const cell = table.rows[0].cells[0];
|
||||
const addEventSpy = jest.spyOn(cell, 'addEventListener');
|
||||
const addEventSpy = vi.spyOn(cell, 'addEventListener');
|
||||
|
||||
utils.initializeResizableColumns(true, table);
|
||||
|
||||
@@ -180,9 +180,9 @@ test('initializeResizableColumns adds event listeners when resizable is true', (
|
||||
|
||||
test('initializeResizableColumns removes event listeners when resizable is false', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const cell = table.rows[0].cells[0];
|
||||
const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
|
||||
const removeEventSpy = vi.spyOn(cell, 'removeEventListener');
|
||||
|
||||
utils.initializeResizableColumns(false, table);
|
||||
|
||||
@@ -200,9 +200,9 @@ test('initializeResizableColumns removes event listeners when resizable is false
|
||||
|
||||
test('initializeDragDropColumns adds event listeners when reorderable is true', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const cell = table.rows[0].cells[0];
|
||||
const addEventSpy = jest.spyOn(cell, 'addEventListener');
|
||||
const addEventSpy = vi.spyOn(cell, 'addEventListener');
|
||||
|
||||
utils.initializeDragDropColumns(true, table);
|
||||
|
||||
@@ -216,9 +216,9 @@ test('initializeDragDropColumns adds event listeners when reorderable is true',
|
||||
|
||||
test('initializeDragDropColumns removes event listeners when reorderable is false', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const cell = table.rows[0].cells[0];
|
||||
const removeEventSpy = jest.spyOn(cell, 'removeEventListener');
|
||||
const removeEventSpy = vi.spyOn(cell, 'removeEventListener');
|
||||
|
||||
utils.initializeDragDropColumns(false, table);
|
||||
|
||||
@@ -232,11 +232,11 @@ test('initializeDragDropColumns removes event listeners when reorderable is fals
|
||||
|
||||
test('handleColumnDragStart sets isDragging and calls setData', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
const row = table.rows[0];
|
||||
const target = row.cells[0] as any;
|
||||
const setDataMock = jest.fn();
|
||||
const setDataMock = vi.fn();
|
||||
const event = {
|
||||
currentTarget: target,
|
||||
dataTransfer: { setData: setDataMock },
|
||||
@@ -253,7 +253,7 @@ test('handleColumnDragStart sets isDragging and calls setData', () => {
|
||||
|
||||
test('handleDragDrop reorders columns when valid drag data exists', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -268,8 +268,8 @@ test('handleDragDrop reorders columns when valid drag data exists', () => {
|
||||
const dropTarget = row.cells[1];
|
||||
const event = {
|
||||
currentTarget: dropTarget,
|
||||
dataTransfer: { getData: jest.fn().mockReturnValue(dragData) },
|
||||
preventDefault: jest.fn(),
|
||||
dataTransfer: { getData: vi.fn().mockReturnValue(dragData) },
|
||||
preventDefault: vi.fn(),
|
||||
} as unknown as DragEvent;
|
||||
|
||||
utils.handleDragDrop(event);
|
||||
@@ -280,7 +280,7 @@ test('handleDragDrop reorders columns when valid drag data exists', () => {
|
||||
|
||||
test('handleDragDrop does nothing when no drag data', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -290,8 +290,8 @@ test('handleDragDrop does nothing when no drag data', () => {
|
||||
const row = table.rows[0];
|
||||
const event = {
|
||||
currentTarget: row.cells[0],
|
||||
dataTransfer: { getData: jest.fn().mockReturnValue('') },
|
||||
preventDefault: jest.fn(),
|
||||
dataTransfer: { getData: vi.fn().mockReturnValue('') },
|
||||
preventDefault: vi.fn(),
|
||||
} as unknown as DragEvent;
|
||||
|
||||
utils.handleDragDrop(event);
|
||||
@@ -302,7 +302,7 @@ test('handleDragDrop does nothing when no drag data', () => {
|
||||
|
||||
test('handleMouseMove updates cursor to col-resize when within resize range', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.resizable = true;
|
||||
|
||||
const target = document.createElement('th') as any;
|
||||
@@ -325,7 +325,7 @@ test('handleMouseMove updates cursor to col-resize when within resize range', ()
|
||||
|
||||
test('handleMouseMove sets default cursor when outside resize range', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.resizable = true;
|
||||
|
||||
const target = document.createElement('th') as any;
|
||||
@@ -348,7 +348,7 @@ test('handleMouseMove sets default cursor when outside resize range', () => {
|
||||
|
||||
test('handleMouseMove resizes column when mouseDown and within bounds', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -384,7 +384,7 @@ test('handleMouseMove resizes column when mouseDown and within bounds', () => {
|
||||
|
||||
test('handleMouseMove skips resize when not resizable', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -406,7 +406,7 @@ test('handleMouseMove skips resize when not resizable', () => {
|
||||
|
||||
test('handleMouseMove handles negative diff by keeping original width', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -442,11 +442,11 @@ test('handleMouseMove handles negative diff by keeping original width', () => {
|
||||
|
||||
test('handleColumnDragStart does not set columnRef when currentTarget is null (line 82 false)', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
const event = {
|
||||
currentTarget: null,
|
||||
dataTransfer: { setData: jest.fn() },
|
||||
dataTransfer: { setData: vi.fn() },
|
||||
} as unknown as DragEvent;
|
||||
|
||||
utils.handleColumnDragStart(event);
|
||||
@@ -457,7 +457,7 @@ test('handleColumnDragStart does not set columnRef when currentTarget is null (l
|
||||
|
||||
test('handleMouseDown does nothing when currentTarget is null (line 118 false)', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
const event = {
|
||||
currentTarget: null,
|
||||
@@ -472,7 +472,7 @@ test('handleMouseDown does nothing when currentTarget is null (line 118 false)',
|
||||
|
||||
test('handleMouseDown does nothing to draggable when outside resize range and not reorderable (line 132 false)', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
utils.reorderable = false;
|
||||
|
||||
const target = document.createElement('th') as any;
|
||||
@@ -494,7 +494,7 @@ test('handleMouseDown does nothing to draggable when outside resize range and no
|
||||
|
||||
test('handleMouseMove skips column update when getColumnIndex returns NaN (line 162 false)', () => {
|
||||
const table = createMockTable(2);
|
||||
const setDerivedColumns = jest.fn();
|
||||
const setDerivedColumns = vi.fn();
|
||||
const utils = new InteractiveTableUtils(
|
||||
table,
|
||||
mockColumns,
|
||||
@@ -509,7 +509,7 @@ test('handleMouseMove skips column update when getColumnIndex returns NaN (line
|
||||
col.oldX = 50;
|
||||
utils.columnRef = col;
|
||||
|
||||
jest.spyOn(utils, 'getColumnIndex').mockReturnValueOnce(NaN);
|
||||
vi.spyOn(utils, 'getColumnIndex').mockReturnValueOnce(NaN);
|
||||
|
||||
const target = document.createElement('th') as any;
|
||||
Object.defineProperty(target, 'offsetWidth', {
|
||||
@@ -531,7 +531,7 @@ test('handleMouseMove skips column update when getColumnIndex returns NaN (line
|
||||
|
||||
test('initializeResizableColumns does nothing when table is null (lines 182-187 false)', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
expect(() => utils.initializeResizableColumns(true, null)).not.toThrow();
|
||||
expect(utils.tableRef).toBeNull();
|
||||
@@ -539,7 +539,7 @@ test('initializeResizableColumns does nothing when table is null (lines 182-187
|
||||
|
||||
test('initializeResizableColumns uses default resizable=false when first arg is undefined (line 182 default branch)', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
utils.initializeResizableColumns(undefined, table);
|
||||
|
||||
@@ -548,7 +548,7 @@ test('initializeResizableColumns uses default resizable=false when first arg is
|
||||
|
||||
test('initializeDragDropColumns does nothing when table is null (lines 206-211 false)', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
expect(() => utils.initializeDragDropColumns(true, null)).not.toThrow();
|
||||
expect(utils.tableRef).toBeNull();
|
||||
@@ -556,7 +556,7 @@ test('initializeDragDropColumns does nothing when table is null (lines 206-211 f
|
||||
|
||||
test('initializeDragDropColumns uses default reorderable=false when first arg is undefined (line 206 default branch)', () => {
|
||||
const table = createMockTable(2);
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
|
||||
utils.initializeDragDropColumns(undefined, table);
|
||||
|
||||
@@ -565,8 +565,8 @@ test('initializeDragDropColumns uses default reorderable=false when first arg is
|
||||
|
||||
test('clearListeners removes document mouseup listener', () => {
|
||||
const table = createMockTable();
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, jest.fn());
|
||||
const removeEventSpy = jest.spyOn(document, 'removeEventListener');
|
||||
const utils = new InteractiveTableUtils(table, mockColumns, vi.fn());
|
||||
const removeEventSpy = vi.spyOn(document, 'removeEventListener');
|
||||
|
||||
utils.clearListeners();
|
||||
|
||||
|
||||
@@ -70,8 +70,8 @@ beforeEach(() => {
|
||||
columns: tableHook.columns,
|
||||
loading: false,
|
||||
highlightRowId: 1,
|
||||
getTableProps: jest.fn(),
|
||||
getTableBodyProps: jest.fn(),
|
||||
getTableProps: vi.fn(),
|
||||
getTableBodyProps: vi.fn(),
|
||||
sticky: false,
|
||||
};
|
||||
});
|
||||
@@ -116,7 +116,7 @@ test('Pagination controls should be rendered when pageSize is provided', () => {
|
||||
pageSize: 2,
|
||||
totalCount: 3,
|
||||
pageIndex: 0,
|
||||
onPageChange: jest.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
};
|
||||
render(<TableCollection {...paginationProps} />);
|
||||
|
||||
@@ -124,7 +124,7 @@ test('Pagination controls should be rendered when pageSize is provided', () => {
|
||||
});
|
||||
|
||||
test('Pagination should call onPageChange when page is changed', async () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
const paginationProps = {
|
||||
...defaultProps,
|
||||
pageSize: 2,
|
||||
@@ -147,7 +147,7 @@ test('Pagination should call onPageChange when page is changed', async () => {
|
||||
});
|
||||
|
||||
test('Pagination callback should be stable across re-renders', () => {
|
||||
const onPageChange = jest.fn();
|
||||
const onPageChange = vi.fn();
|
||||
const paginationProps = {
|
||||
...defaultProps,
|
||||
pageSize: 2,
|
||||
@@ -171,7 +171,7 @@ test('Should display correct page info when showRowCount is true', () => {
|
||||
pageSize: 2,
|
||||
totalCount: 3,
|
||||
pageIndex: 0,
|
||||
onPageChange: jest.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
showRowCount: true,
|
||||
};
|
||||
render(<TableCollection {...paginationProps} />);
|
||||
@@ -186,7 +186,7 @@ test('Should not display page info when showRowCount is false', () => {
|
||||
pageSize: 2,
|
||||
totalCount: 3,
|
||||
pageIndex: 0,
|
||||
onPageChange: jest.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
showRowCount: false,
|
||||
};
|
||||
render(<TableCollection {...paginationProps} />);
|
||||
@@ -196,8 +196,8 @@ test('Should not display page info when showRowCount is false', () => {
|
||||
});
|
||||
|
||||
test('Bulk selection should work with pagination', () => {
|
||||
const toggleRowSelected = jest.fn();
|
||||
const toggleAllRowsSelected = jest.fn();
|
||||
const toggleRowSelected = vi.fn();
|
||||
const toggleAllRowsSelected = vi.fn();
|
||||
const selectionProps = {
|
||||
...defaultProps,
|
||||
bulkSelectEnabled: true,
|
||||
@@ -207,7 +207,7 @@ test('Bulk selection should work with pagination', () => {
|
||||
pageSize: 2,
|
||||
totalCount: 3,
|
||||
pageIndex: 0,
|
||||
onPageChange: jest.fn(),
|
||||
onPageChange: vi.fn(),
|
||||
};
|
||||
render(<TableCollection {...selectionProps} />);
|
||||
|
||||
@@ -217,7 +217,7 @@ test('Bulk selection should work with pagination', () => {
|
||||
});
|
||||
|
||||
test('should call setSortBy when clicking sortable column header', () => {
|
||||
const setSortBy = jest.fn();
|
||||
const setSortBy = vi.fn();
|
||||
const sortingProps = {
|
||||
...defaultProps,
|
||||
setSortBy,
|
||||
|
||||
@@ -229,7 +229,7 @@ test('should render the right wrap content text by columnsForWrapText', () => {
|
||||
});
|
||||
|
||||
test('should handle server-side pagination', async () => {
|
||||
const onServerPagination = jest.fn();
|
||||
const onServerPagination = vi.fn();
|
||||
const serverPaginationProps = {
|
||||
...mockedProps,
|
||||
serverPagination: true,
|
||||
@@ -251,7 +251,7 @@ test('should handle server-side pagination', async () => {
|
||||
});
|
||||
|
||||
test('should handle server-side sorting', async () => {
|
||||
const onServerPagination = jest.fn();
|
||||
const onServerPagination = vi.fn();
|
||||
const serverPaginationProps = {
|
||||
...mockedProps,
|
||||
serverPagination: true,
|
||||
@@ -271,7 +271,7 @@ test('should handle server-side sorting', async () => {
|
||||
});
|
||||
|
||||
test('pagination callbacks should be stable across re-renders', () => {
|
||||
const onServerPagination = jest.fn();
|
||||
const onServerPagination = vi.fn();
|
||||
const serverPaginationProps = {
|
||||
...mockedProps,
|
||||
serverPagination: true,
|
||||
@@ -290,9 +290,7 @@ test('pagination callbacks should be stable across re-renders', () => {
|
||||
});
|
||||
|
||||
test('should scroll to top when scrollTopOnPagination is true', async () => {
|
||||
const scrollToSpy = jest
|
||||
.spyOn(window, 'scrollTo')
|
||||
.mockImplementation(() => {});
|
||||
const scrollToSpy = vi.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
||||
|
||||
const scrollProps = {
|
||||
...mockedProps,
|
||||
@@ -313,9 +311,7 @@ test('should scroll to top when scrollTopOnPagination is true', async () => {
|
||||
});
|
||||
|
||||
test('should NOT scroll to top when scrollTopOnPagination is false', async () => {
|
||||
const scrollToSpy = jest
|
||||
.spyOn(window, 'scrollTo')
|
||||
.mockImplementation(() => {});
|
||||
const scrollToSpy = vi.spyOn(window, 'scrollTo').mockImplementation(() => {});
|
||||
|
||||
const scrollProps = {
|
||||
...mockedProps,
|
||||
|
||||
@@ -108,7 +108,7 @@ describe('Tabs', () => {
|
||||
});
|
||||
|
||||
test('should handle tab change events', () => {
|
||||
const onChangeMock = jest.fn();
|
||||
const onChangeMock = vi.fn();
|
||||
const { getByText } = render(
|
||||
<Tabs items={defaultItems} onChange={onChangeMock} />,
|
||||
);
|
||||
@@ -119,7 +119,7 @@ describe('Tabs', () => {
|
||||
});
|
||||
|
||||
test('should pass through additional props to Antd Tabs', () => {
|
||||
const onTabClickMock = jest.fn();
|
||||
const onTabClickMock = vi.fn();
|
||||
const { getByText } = render(
|
||||
<Tabs
|
||||
items={defaultItems}
|
||||
@@ -146,7 +146,7 @@ describe('Tabs', () => {
|
||||
});
|
||||
|
||||
test('should handle onEdit callback for add/remove actions', () => {
|
||||
const onEditMock = jest.fn();
|
||||
const onEditMock = vi.fn();
|
||||
const itemsWithRemove = defaultItems.map(item => ({
|
||||
...item,
|
||||
closable: true,
|
||||
|
||||
@@ -22,16 +22,17 @@ import { createRef } from 'react';
|
||||
import { ThemeProvider, supersetTheme } from '@apache-superset/core/theme';
|
||||
import * as uiModule from '@apache-superset/core/theme';
|
||||
import { ThemedAgGridReact } from './index';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
// Mock useThemeMode hook
|
||||
jest.mock('@apache-superset/core/theme', () => ({
|
||||
...jest.requireActual('@apache-superset/core/theme'),
|
||||
useThemeMode: jest.fn(() => false), // Default to light mode
|
||||
vi.mock('@apache-superset/core/theme', async (importActual) => ({
|
||||
...(await importActual()),
|
||||
useThemeMode: vi.fn(() => false), // Default to light mode
|
||||
}));
|
||||
|
||||
// Mock ag-grid-react to avoid complex setup
|
||||
jest.mock('ag-grid-react', () => ({
|
||||
AgGridReact: jest.fn(({ theme, ...props }) => (
|
||||
vi.mock('ag-grid-react', () => ({
|
||||
AgGridReact: vi.fn(({ theme, ...props }) => (
|
||||
<div
|
||||
data-test="ag-grid-react"
|
||||
data-theme={JSON.stringify(theme)}
|
||||
@@ -43,16 +44,16 @@ jest.mock('ag-grid-react', () => ({
|
||||
}));
|
||||
|
||||
// Mock ag-grid-community
|
||||
jest.mock('ag-grid-community', () => ({
|
||||
vi.mock('ag-grid-community', () => ({
|
||||
themeQuartz: {
|
||||
withPart: jest.fn().mockReturnThis(),
|
||||
withParams: jest.fn(params => ({ ...params, _type: 'theme' })),
|
||||
withPart: vi.fn().mockReturnThis(),
|
||||
withParams: vi.fn(params => ({ ...params, _type: 'theme' })),
|
||||
},
|
||||
colorSchemeDark: { _type: 'dark' },
|
||||
colorSchemeLight: { _type: 'light' },
|
||||
AllCommunityModule: {},
|
||||
ClientSideRowModelModule: {},
|
||||
ModuleRegistry: { registerModules: jest.fn() },
|
||||
ModuleRegistry: { registerModules: vi.fn() },
|
||||
}));
|
||||
|
||||
const mockRowData = [
|
||||
@@ -66,9 +67,9 @@ const mockColumnDefs = [
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
// Reset to light mode by default
|
||||
(uiModule.useThemeMode as jest.Mock).mockReturnValue(false);
|
||||
(uiModule.useThemeMode as Mock).mockReturnValue(false);
|
||||
});
|
||||
|
||||
test('renders the AgGridReact component', () => {
|
||||
@@ -101,7 +102,7 @@ test('applies light theme when background is light', () => {
|
||||
|
||||
test('applies dark theme when background is dark', () => {
|
||||
// Mock dark mode
|
||||
(uiModule.useThemeMode as jest.Mock).mockReturnValue(true);
|
||||
(uiModule.useThemeMode as Mock).mockReturnValue(true);
|
||||
|
||||
const darkTheme = {
|
||||
...supersetTheme,
|
||||
@@ -144,8 +145,8 @@ test('forwards ref to AgGridReact', () => {
|
||||
});
|
||||
|
||||
test('passes all props through to AgGridReact', () => {
|
||||
const onGridReady = jest.fn();
|
||||
const onCellClicked = jest.fn();
|
||||
const onGridReady = vi.fn();
|
||||
const onCellClicked = vi.fn();
|
||||
|
||||
render(
|
||||
<ThemedAgGridReact
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
*/
|
||||
import { ModuleRegistry } from 'ag-grid-community';
|
||||
import { setupAGGridModules, defaultModules } from './setupAGGridModules';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
jest.mock('ag-grid-community', () => ({
|
||||
vi.mock('ag-grid-community', () => ({
|
||||
ModuleRegistry: {
|
||||
registerModules: jest.fn(),
|
||||
registerModules: vi.fn(),
|
||||
},
|
||||
ColumnAutoSizeModule: {
|
||||
moduleName: 'ColumnAutoSizeModule',
|
||||
@@ -52,7 +53,7 @@ jest.mock('ag-grid-community', () => ({
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('defaultModules exports an array of AG Grid modules', () => {
|
||||
@@ -88,7 +89,7 @@ test('setupAGGridModules registers default + additional modules when provided',
|
||||
|
||||
expect(ModuleRegistry.registerModules).toHaveBeenCalledTimes(1);
|
||||
|
||||
const registeredModules = (ModuleRegistry.registerModules as jest.Mock).mock
|
||||
const registeredModules = (ModuleRegistry.registerModules as Mock).mock
|
||||
.calls[0][0];
|
||||
|
||||
// Should contain all default modules
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { render, waitFor } from '@superset-ui/core/spec';
|
||||
// import { render, waitFor } from '@testing-library/react';
|
||||
import { Timer, TimerProps } from '.';
|
||||
import { now } from '../../utils/dates';
|
||||
|
||||
|
||||
@@ -47,11 +47,11 @@ const mockTimezones = [
|
||||
];
|
||||
|
||||
beforeAll(() => {
|
||||
global.Intl.supportedValuesOf = jest.fn(() => mockTimezones);
|
||||
global.Intl.supportedValuesOf = vi.fn(() => mockTimezones);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('initializes with empty cache', () => {
|
||||
@@ -229,7 +229,7 @@ test('allows retry after failed computation', async () => {
|
||||
});
|
||||
|
||||
test('uses queueMicrotask when available', async () => {
|
||||
const queueMicrotaskSpy = jest.spyOn(global, 'queueMicrotask');
|
||||
const queueMicrotaskSpy = vi.spyOn(global, 'queueMicrotask');
|
||||
const cache = new TimezoneOptionsCache(mockGetOffsetKey, mockOffsetsToName);
|
||||
|
||||
await cache.getOptionsAsync();
|
||||
@@ -244,7 +244,7 @@ test('falls back to setTimeout when queueMicrotask is not available', async () =
|
||||
// @ts-expect-error - temporarily remove queueMicrotask for testing
|
||||
delete global.queueMicrotask;
|
||||
|
||||
const setTimeoutSpy = jest.spyOn(global, 'setTimeout');
|
||||
const setTimeoutSpy = vi.spyOn(global, 'setTimeout');
|
||||
const cache = new TimezoneOptionsCache(mockGetOffsetKey, mockOffsetsToName);
|
||||
|
||||
await cache.getOptionsAsync();
|
||||
|
||||
@@ -24,8 +24,8 @@ import type { TimezoneSelectorProps } from './index';
|
||||
|
||||
const loadComponent = (mockCurrentTime?: string) => {
|
||||
if (mockCurrentTime) {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(new Date(mockCurrentTime));
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date(mockCurrentTime));
|
||||
}
|
||||
return new Promise<FC<TimezoneSelectorProps>>(resolve => {
|
||||
const { default: TimezoneSelector } = module.require('./index');
|
||||
@@ -34,12 +34,12 @@ const loadComponent = (mockCurrentTime?: string) => {
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test('render timezones in correct order for daylight saving time', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-07-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(
|
||||
<TimezoneSelector
|
||||
onTimezoneChange={onTimezoneChange}
|
||||
|
||||
@@ -24,12 +24,13 @@ import type { TimezoneSelectorProps } from './index';
|
||||
|
||||
const loadComponent = (mockCurrentTime?: string) => {
|
||||
if (mockCurrentTime) {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(new Date(mockCurrentTime));
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date(mockCurrentTime));
|
||||
}
|
||||
return new Promise<FC<TimezoneSelectorProps>>(resolve => {
|
||||
const { default: TimezoneSelector } = module.require('./index');
|
||||
resolve(TimezoneSelector);
|
||||
import('./index').then(({ default: TimezoneSelector }) => {
|
||||
resolve(TimezoneSelector);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -41,15 +42,15 @@ const openSelectMenu = () => {
|
||||
userEvent.click(searchInput);
|
||||
};
|
||||
|
||||
jest.spyOn(extendedDayjs.tz, 'guess').mockReturnValue('America/New_York');
|
||||
vi.spyOn(extendedDayjs.tz, 'guess').mockReturnValue('America/New_York');
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test('use the timezone from `dayjs` if no timezone provided', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(<TimezoneSelector onTimezoneChange={onTimezoneChange} />);
|
||||
// Wait for async loading and default timezone to be set
|
||||
await screen.findByText('GMT -05:00 (Eastern Standard Time)');
|
||||
@@ -58,7 +59,7 @@ test('use the timezone from `dayjs` if no timezone provided', async () => {
|
||||
|
||||
test('update to closest deduped timezone when timezone is provided', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(
|
||||
<TimezoneSelector
|
||||
onTimezoneChange={onTimezoneChange}
|
||||
@@ -77,7 +78,7 @@ test('update to closest deduped timezone when timezone is provided', async () =>
|
||||
|
||||
test('use the default timezone when an invalid timezone is provided', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(
|
||||
<TimezoneSelector onTimezoneChange={onTimezoneChange} timezone="UTC" />,
|
||||
);
|
||||
@@ -93,7 +94,7 @@ test('use the default timezone when an invalid timezone is provided', async () =
|
||||
|
||||
test('render timezones in correct order for standard time', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(
|
||||
<TimezoneSelector
|
||||
onTimezoneChange={onTimezoneChange}
|
||||
@@ -111,7 +112,7 @@ test('render timezones in correct order for standard time', async () => {
|
||||
|
||||
test('can select a timezone values and returns canonical timezone name', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
render(
|
||||
<TimezoneSelector
|
||||
onTimezoneChange={onTimezoneChange}
|
||||
@@ -134,7 +135,7 @@ test('can select a timezone values and returns canonical timezone name', async (
|
||||
|
||||
test('can update props and rerender with different values', async () => {
|
||||
const TimezoneSelector = await loadComponent('2022-01-01');
|
||||
const onTimezoneChange = jest.fn();
|
||||
const onTimezoneChange = vi.fn();
|
||||
const { rerender } = render(
|
||||
<TimezoneSelector
|
||||
onTimezoneChange={onTimezoneChange}
|
||||
|
||||
@@ -46,9 +46,9 @@ test('should render the UnsavedChangesModal component if showModal is true', asy
|
||||
});
|
||||
|
||||
test('should only call onConfirmNavigation when clicking the Discard button', async () => {
|
||||
const mockOnHide = jest.fn();
|
||||
const mockHandleSave = jest.fn();
|
||||
const mockOnConfirmNavigation = jest.fn();
|
||||
const mockOnHide = vi.fn();
|
||||
const mockHandleSave = vi.fn();
|
||||
const mockOnConfirmNavigation = vi.fn();
|
||||
|
||||
render(
|
||||
<UnsavedChangesModal
|
||||
@@ -71,9 +71,9 @@ test('should only call onConfirmNavigation when clicking the Discard button', as
|
||||
});
|
||||
|
||||
test('should only call handleSave when clicking the Save button', async () => {
|
||||
const mockOnHide = jest.fn();
|
||||
const mockHandleSave = jest.fn();
|
||||
const mockOnConfirmNavigation = jest.fn();
|
||||
const mockOnHide = vi.fn();
|
||||
const mockHandleSave = vi.fn();
|
||||
const mockOnConfirmNavigation = vi.fn();
|
||||
|
||||
render(
|
||||
<UnsavedChangesModal
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Button, Upload } from '..';
|
||||
|
||||
describe('Upload Component', () => {
|
||||
test('renders upload button and triggers file upload', async () => {
|
||||
const handleChange = jest.fn();
|
||||
const handleChange = vi.fn();
|
||||
|
||||
render(
|
||||
<Upload onChange={handleChange}>
|
||||
|
||||
@@ -20,7 +20,7 @@ import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useChangeEffect } from './useChangeEffect';
|
||||
|
||||
test('call callback the first time with undefined and value', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
renderHook(props => useChangeEffect(props.value, props.callback), {
|
||||
initialProps: { value: 'value', callback },
|
||||
});
|
||||
@@ -29,7 +29,7 @@ test('call callback the first time with undefined and value', () => {
|
||||
});
|
||||
|
||||
test('do not call callback 2 times if the value do not change', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
const hook = renderHook(
|
||||
props => useChangeEffect(props.value, props.callback),
|
||||
{
|
||||
@@ -41,7 +41,7 @@ test('do not call callback 2 times if the value do not change', () => {
|
||||
});
|
||||
|
||||
test('call callback whenever the value changes', () => {
|
||||
const callback = jest.fn();
|
||||
const callback = vi.fn();
|
||||
const hook = renderHook(
|
||||
props => useChangeEffect(props.value, props.callback),
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useComponentDidMount } from './useComponentDidMount';
|
||||
|
||||
test('the effect should only be executed on the first render', () => {
|
||||
const effect = jest.fn();
|
||||
const effect = vi.fn();
|
||||
const hook = renderHook(() => useComponentDidMount(effect));
|
||||
expect(effect).toHaveBeenCalledTimes(1);
|
||||
hook.rerender();
|
||||
|
||||
@@ -20,12 +20,12 @@ import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useComponentDidUpdate } from './useComponentDidUpdate';
|
||||
|
||||
test('the effect should not be executed on the first render', () => {
|
||||
const effect = jest.fn();
|
||||
const effect = vi.fn();
|
||||
const hook = renderHook(props => useComponentDidUpdate(props.effect), {
|
||||
initialProps: { effect },
|
||||
});
|
||||
expect(effect).toHaveBeenCalledTimes(0);
|
||||
const changedEffect = jest.fn();
|
||||
const changedEffect = vi.fn();
|
||||
hook.rerender({ effect: changedEffect });
|
||||
expect(changedEffect).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -19,9 +19,11 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useElementOnScreen } from './useElementOnScreen';
|
||||
|
||||
const observeMock = jest.fn();
|
||||
const unobserveMock = jest.fn();
|
||||
const IntersectionObserverMock = jest.fn();
|
||||
vi.mock('react', { spy: true });
|
||||
|
||||
const observeMock = vi.fn();
|
||||
const unobserveMock = vi.fn();
|
||||
const IntersectionObserverMock = vi.fn();
|
||||
IntersectionObserverMock.prototype.observe = observeMock;
|
||||
IntersectionObserverMock.prototype.unobserve = unobserveMock;
|
||||
|
||||
@@ -31,7 +33,7 @@ beforeEach(() => {
|
||||
|
||||
afterEach(() => {
|
||||
IntersectionObserverMock.mockClear();
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should return null and false on first render', () => {
|
||||
@@ -66,7 +68,7 @@ test('should return isSticky as false when intersectionRatio >= 1', async () =>
|
||||
});
|
||||
|
||||
test('should observe and unobserve element with IntersectionObserver', async () => {
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: 'test' });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: 'test' });
|
||||
const options = { threshold: 0.5 };
|
||||
const { result, unmount } = renderHook(() => useElementOnScreen(options));
|
||||
const [elementRef] = result.current;
|
||||
@@ -85,7 +87,7 @@ test('should observe and unobserve element with IntersectionObserver', async ()
|
||||
});
|
||||
|
||||
test('should not observe an element if it is null', () => {
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: null });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: null });
|
||||
const options = {};
|
||||
const { result } = renderHook(() => useElementOnScreen(options));
|
||||
const [ref, isSticky] = result.current;
|
||||
@@ -96,7 +98,7 @@ test('should not observe an element if it is null', () => {
|
||||
});
|
||||
|
||||
test('should not unobserve the element if it is null', () => {
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: null });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: null });
|
||||
const options = {};
|
||||
const { result, unmount } = renderHook(() => useElementOnScreen(options));
|
||||
const [ref, isSticky] = result.current;
|
||||
|
||||
@@ -20,7 +20,7 @@ import { renderHook } from '@testing-library/react-hooks';
|
||||
import useCSSTextTruncation from './useCSSTextTruncation';
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
test('should be false by default', () => {
|
||||
@@ -36,7 +36,7 @@ test('should not truncate', () => {
|
||||
const ref = { current: document.createElement('p') };
|
||||
Object.defineProperty(ref.current, 'offsetWidth', { get: () => 100 });
|
||||
Object.defineProperty(ref.current, 'scrollWidth', { get: () => 50 });
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useCSSTextTruncation<HTMLParagraphElement>(),
|
||||
@@ -50,7 +50,7 @@ test('should truncate', () => {
|
||||
const ref = { current: document.createElement('p') };
|
||||
Object.defineProperty(ref.current, 'offsetWidth', { get: () => 50 });
|
||||
Object.defineProperty(ref.current, 'scrollWidth', { get: () => 100 });
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useCSSTextTruncation<HTMLParagraphElement>(),
|
||||
@@ -64,7 +64,7 @@ test('should not truncate with vertical orientation', () => {
|
||||
const ref = { current: document.createElement('p') };
|
||||
Object.defineProperty(ref.current, 'offsetHeight', { get: () => 100 });
|
||||
Object.defineProperty(ref.current, 'scrollHeight', { get: () => 50 });
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useCSSTextTruncation<HTMLParagraphElement>({
|
||||
@@ -81,7 +81,7 @@ test('should truncate with vertical orientation', () => {
|
||||
const ref = { current: document.createElement('p') };
|
||||
Object.defineProperty(ref.current, 'offsetHeight', { get: () => 50 });
|
||||
Object.defineProperty(ref.current, 'scrollHeight', { get: () => 100 });
|
||||
jest.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
vi.spyOn(global.React, 'useRef').mockReturnValue({ current: ref.current });
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useCSSTextTruncation<HTMLParagraphElement>({
|
||||
|
||||
@@ -19,9 +19,10 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { RefObject } from 'react';
|
||||
import useChildElementTruncation from './useChildElementTruncation';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
let observeMock: jest.Mock;
|
||||
let disconnectMock: jest.Mock;
|
||||
let observeMock: Mock;
|
||||
let disconnectMock: Mock;
|
||||
let originalResizeObserver: typeof ResizeObserver;
|
||||
|
||||
const genElements = (
|
||||
@@ -79,12 +80,14 @@ beforeAll(() => {
|
||||
originalResizeObserver = window.ResizeObserver;
|
||||
|
||||
// Mock ResizeObserver
|
||||
observeMock = jest.fn();
|
||||
disconnectMock = jest.fn();
|
||||
window.ResizeObserver = jest.fn(() => ({
|
||||
observe: observeMock,
|
||||
disconnect: disconnectMock,
|
||||
})) as unknown as typeof ResizeObserver;
|
||||
observeMock = vi.fn();
|
||||
disconnectMock = vi.fn();
|
||||
window.ResizeObserver = vi.fn(function () {
|
||||
return {
|
||||
observe: observeMock,
|
||||
disconnect: disconnectMock,
|
||||
};
|
||||
} as unknown as typeof window.ResizeObserver);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { ReactElement } from 'react';
|
||||
import { render, RenderOptions } from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import '@testing-library/jest-dom/vitest';
|
||||
import { themeObject } from '@apache-superset/core/theme';
|
||||
|
||||
// Define the wrapper component outside
|
||||
|
||||
@@ -32,7 +32,7 @@ test('withLabel prepends label to validator error message', () => {
|
||||
});
|
||||
|
||||
test('withLabel passes value and state to underlying validator', () => {
|
||||
const validator = jest.fn(() => false as false);
|
||||
const validator = vi.fn(() => false as false);
|
||||
const labeled = withLabel(validator, 'Field');
|
||||
labeled('value', { someState: true });
|
||||
expect(validator).toHaveBeenCalledWith('value', { someState: true });
|
||||
|
||||
@@ -21,15 +21,15 @@ import { triggerResizeObserver } from 'resize-observer-polyfill';
|
||||
import { promiseTimeout, WithLegend } from '@superset-ui/core';
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
let renderChart = jest.fn();
|
||||
let renderLegend = jest.fn();
|
||||
let renderChart = vi.fn();
|
||||
let renderLegend = vi.fn();
|
||||
|
||||
// TODO: rewrite to rtl
|
||||
/* oxlint-disable-next-line jest/no-disabled-tests */
|
||||
describe.skip('WithLegend', () => {
|
||||
beforeEach(() => {
|
||||
renderChart = jest.fn(() => <div className="chart" />);
|
||||
renderLegend = jest.fn(() => <div className="legend" />);
|
||||
renderChart = vi.fn(() => <div className="chart" />);
|
||||
renderLegend = vi.fn(() => <div className="legend" />);
|
||||
});
|
||||
|
||||
test('sets className', () => {
|
||||
|
||||
@@ -18,23 +18,11 @@
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
import { render, screen, act } from '@testing-library/react';
|
||||
import ChartClient from '../../../src/chart/clients/ChartClient';
|
||||
import ChartDataProvider, {
|
||||
ChartDataProviderProps,
|
||||
} from '../../../src/chart/components/ChartDataProvider';
|
||||
import { bigNumberFormData } from '../fixtures/formData';
|
||||
|
||||
// Keep existing mock setup
|
||||
const defaultMockLoadFormData = jest.fn(({ formData }: { formData: unknown }) =>
|
||||
Promise.resolve(formData),
|
||||
);
|
||||
|
||||
type MockLoadFormData =
|
||||
| typeof defaultMockLoadFormData
|
||||
| jest.Mock<Promise<unknown>, unknown[]>;
|
||||
|
||||
let mockLoadFormData: MockLoadFormData = defaultMockLoadFormData;
|
||||
|
||||
function createPromise<T>(input: T) {
|
||||
return Promise.resolve(input);
|
||||
}
|
||||
@@ -43,24 +31,34 @@ function createArrayPromise<T>(input: T) {
|
||||
return Promise.resolve([input]);
|
||||
}
|
||||
|
||||
const mockLoadDatasource = jest.fn<Promise<unknown>, unknown[]>(createPromise);
|
||||
const mockLoadQueryData = jest.fn<Promise<unknown>, unknown[]>(
|
||||
createArrayPromise,
|
||||
const { mockLoadDatasource, mockLoadQueryData, mockLoadFormData } = vi.hoisted(
|
||||
() => ({
|
||||
mockLoadDatasource: vi.fn().mockImplementation(createPromise),
|
||||
mockLoadQueryData: vi.fn().mockImplementation(createArrayPromise),
|
||||
mockLoadFormData: vi.fn(({ formData }: { formData: unknown }) =>
|
||||
Promise.resolve(formData),
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
const actual = jest.requireActual('../../../src/chart/clients/ChartClient');
|
||||
jest.spyOn(actual, 'default').mockImplementation(() => ({
|
||||
loadDatasource: mockLoadDatasource,
|
||||
loadFormData: mockLoadFormData,
|
||||
loadQueryData: mockLoadQueryData,
|
||||
}));
|
||||
|
||||
const ChartClientMock = ChartClient as jest.Mock<ChartClient>;
|
||||
vi.mock('../../../src/chart/clients/ChartClient', async importActual => {
|
||||
const actual = (await importActual()) as Record<any, any>;
|
||||
return {
|
||||
...actual,
|
||||
default: function () {
|
||||
return {
|
||||
...actual.default,
|
||||
loadDatasource: mockLoadDatasource,
|
||||
loadFormData: mockLoadFormData,
|
||||
loadQueryData: mockLoadQueryData,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
describe('ChartDataProvider', () => {
|
||||
beforeEach(() => {
|
||||
ChartClientMock.mockClear();
|
||||
mockLoadFormData = defaultMockLoadFormData;
|
||||
mockLoadFormData.mockClear();
|
||||
mockLoadFormData.mockClear();
|
||||
mockLoadDatasource.mockClear();
|
||||
mockLoadQueryData.mockClear();
|
||||
@@ -81,11 +79,6 @@ describe('ChartDataProvider', () => {
|
||||
return render(<ChartDataProvider {...props} {...overrideProps} />);
|
||||
}
|
||||
|
||||
test('instantiates a new ChartClient()', () => {
|
||||
setup();
|
||||
expect(ChartClientMock).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
describe('ChartClient.loadFormData', () => {
|
||||
test('calls method on mount', () => {
|
||||
setup();
|
||||
@@ -100,7 +93,7 @@ describe('ChartDataProvider', () => {
|
||||
const options = { host: 'override' };
|
||||
setup({ formDataRequestOptions: options });
|
||||
expect(mockLoadFormData).toHaveBeenCalledTimes(1);
|
||||
expect(mockLoadFormData.mock.calls[0][1]).toEqual(options);
|
||||
expect((mockLoadFormData.mock.calls[0] as any[])[1]).toEqual(options);
|
||||
});
|
||||
|
||||
test('calls ChartClient.loadFormData when formData or sliceId change', async () => {
|
||||
@@ -277,7 +270,7 @@ describe('ChartDataProvider', () => {
|
||||
|
||||
describe('callbacks', () => {
|
||||
test('calls onLoaded when loaded', async () => {
|
||||
const onLoaded = jest.fn();
|
||||
const onLoaded = vi.fn();
|
||||
mockLoadFormData.mockResolvedValue(props.formData);
|
||||
mockLoadQueryData.mockResolvedValue([props.formData]);
|
||||
mockLoadDatasource.mockResolvedValue(props.formData.datasource);
|
||||
@@ -297,7 +290,7 @@ describe('ChartDataProvider', () => {
|
||||
});
|
||||
|
||||
test('calls onError upon request error', async () => {
|
||||
const onError = jest.fn();
|
||||
const onError = vi.fn();
|
||||
mockLoadFormData.mockRejectedValue(new Error('error'));
|
||||
|
||||
setup({ onError });
|
||||
@@ -311,7 +304,7 @@ describe('ChartDataProvider', () => {
|
||||
});
|
||||
|
||||
test('calls onError upon JS error', async () => {
|
||||
const onError = jest.fn();
|
||||
const onError = vi.fn();
|
||||
mockLoadFormData.mockImplementation(() => {
|
||||
throw new Error('non-async error');
|
||||
});
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import { render, screen } from '@superset-ui/core/spec';
|
||||
import mockConsole, { RestoreConsole } from 'jest-mock-console';
|
||||
import { triggerResizeObserver } from 'resize-observer-polyfill';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
|
||||
@@ -34,18 +33,19 @@ import {
|
||||
|
||||
import { isMatrixifyEnabled } from '../../../src/chart/types/matrixify';
|
||||
import MatrixifyGridRenderer from '../../../src/chart/components/Matrixify/MatrixifyGridRenderer';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
// Mock Matrixify imports
|
||||
jest.mock('../../../src/chart/types/matrixify', () => ({
|
||||
isMatrixifyEnabled: jest.fn(() => false),
|
||||
getMatrixifyConfig: jest.fn(() => null),
|
||||
vi.mock('../../../src/chart/types/matrixify', () => ({
|
||||
isMatrixifyEnabled: vi.fn(() => false),
|
||||
getMatrixifyConfig: vi.fn(() => null),
|
||||
}));
|
||||
|
||||
jest.mock(
|
||||
vi.mock(
|
||||
'../../../src/chart/components/Matrixify/MatrixifyGridRenderer',
|
||||
() => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(() => null),
|
||||
default: vi.fn(() => null),
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -63,9 +63,7 @@ function getDimensionText(container: HTMLElement) {
|
||||
}
|
||||
|
||||
describe('SuperChart', () => {
|
||||
jest.setTimeout(5000);
|
||||
|
||||
let restoreConsole: RestoreConsole;
|
||||
vi.setConfig({ testTimeout: 5000 });
|
||||
|
||||
const plugins = [
|
||||
new DiligentChartPlugin().configure({ key: ChartKeys.DILIGENT }),
|
||||
@@ -78,15 +76,6 @@ describe('SuperChart', () => {
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
restoreConsole = mockConsole();
|
||||
triggerResizeObserver([]); // Reset any pending resize observers
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
describe('includes ErrorBoundary', () => {
|
||||
let expectedErrors = 0;
|
||||
let actualErrors = 0;
|
||||
@@ -128,9 +117,7 @@ describe('SuperChart', () => {
|
||||
|
||||
test('renders custom FallbackComponent', async () => {
|
||||
expectedErrors = 1;
|
||||
const CustomFallbackComponent = jest.fn(() => (
|
||||
<div>Custom Fallback!</div>
|
||||
));
|
||||
const CustomFallbackComponent = vi.fn(() => <div>Custom Fallback!</div>);
|
||||
|
||||
render(
|
||||
<SuperChart
|
||||
@@ -147,7 +134,7 @@ describe('SuperChart', () => {
|
||||
});
|
||||
test('call onErrorBoundary', async () => {
|
||||
expectedErrors = 1;
|
||||
const handleError = jest.fn();
|
||||
const handleError = vi.fn();
|
||||
render(
|
||||
<SuperChart
|
||||
chartType={ChartKeys.BUGGY}
|
||||
@@ -165,8 +152,8 @@ describe('SuperChart', () => {
|
||||
// Update the test cases
|
||||
test('does not include ErrorBoundary if told so', async () => {
|
||||
expectedErrors = 1;
|
||||
const inactiveErrorHandler = jest.fn();
|
||||
const activeErrorHandler = jest.fn();
|
||||
const inactiveErrorHandler = vi.fn();
|
||||
const activeErrorHandler = vi.fn();
|
||||
render(
|
||||
<ErrorBoundary
|
||||
fallbackRender={() => <div>Error!</div>}
|
||||
@@ -195,7 +182,7 @@ describe('SuperChart', () => {
|
||||
|
||||
// Update test cases
|
||||
// Update timeout for all async tests
|
||||
jest.setTimeout(10000);
|
||||
vi.setConfig({ testTimeout: 10000 });
|
||||
|
||||
// Update the props test to wait for component to render
|
||||
test('passes the props to renderer correctly', async () => {
|
||||
@@ -229,7 +216,7 @@ describe('SuperChart', () => {
|
||||
|
||||
// Update dimension tests to wait for resize observer
|
||||
// First, increase the timeout for all tests
|
||||
jest.setTimeout(20000);
|
||||
vi.setConfig({ testTimeout: 20000 });
|
||||
|
||||
// Update the waitForDimensions helper to include a retry mechanism
|
||||
// Update waitForDimensions to avoid await in loop
|
||||
@@ -460,13 +447,12 @@ describe('SuperChart', () => {
|
||||
});
|
||||
|
||||
test('should render MatrixifyGridRenderer when matrixify is enabled with empty data', () => {
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as jest.MockedFunction<
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as Mock<
|
||||
typeof isMatrixifyEnabled
|
||||
>;
|
||||
const mockMatrixifyGridRenderer =
|
||||
MatrixifyGridRenderer as jest.MockedFunction<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
const mockMatrixifyGridRenderer = MatrixifyGridRenderer as Mock<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
|
||||
mockIsMatrixifyEnabled.mockReturnValue(true);
|
||||
|
||||
@@ -485,13 +471,12 @@ describe('SuperChart', () => {
|
||||
});
|
||||
|
||||
test('should render MatrixifyGridRenderer when matrixify is enabled with null data', () => {
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as jest.MockedFunction<
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as Mock<
|
||||
typeof isMatrixifyEnabled
|
||||
>;
|
||||
const mockMatrixifyGridRenderer =
|
||||
MatrixifyGridRenderer as jest.MockedFunction<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
const mockMatrixifyGridRenderer = MatrixifyGridRenderer as Mock<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
|
||||
mockIsMatrixifyEnabled.mockReturnValue(true);
|
||||
|
||||
@@ -510,13 +495,12 @@ describe('SuperChart', () => {
|
||||
});
|
||||
|
||||
test('should ignore custom noResults component when matrixify is enabled', () => {
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as jest.MockedFunction<
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as Mock<
|
||||
typeof isMatrixifyEnabled
|
||||
>;
|
||||
const mockMatrixifyGridRenderer =
|
||||
MatrixifyGridRenderer as jest.MockedFunction<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
const mockMatrixifyGridRenderer = MatrixifyGridRenderer as Mock<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
|
||||
mockIsMatrixifyEnabled.mockReturnValue(true);
|
||||
|
||||
@@ -540,16 +524,15 @@ describe('SuperChart', () => {
|
||||
});
|
||||
|
||||
test('should apply error boundary to matrixify grid renderer', () => {
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as jest.MockedFunction<
|
||||
const mockIsMatrixifyEnabled = isMatrixifyEnabled as Mock<
|
||||
typeof isMatrixifyEnabled
|
||||
>;
|
||||
const mockMatrixifyGridRenderer =
|
||||
MatrixifyGridRenderer as jest.MockedFunction<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
const mockMatrixifyGridRenderer = MatrixifyGridRenderer as Mock<
|
||||
typeof MatrixifyGridRenderer
|
||||
>;
|
||||
|
||||
mockIsMatrixifyEnabled.mockReturnValue(true);
|
||||
const onErrorBoundary = jest.fn();
|
||||
const onErrorBoundary = vi.fn();
|
||||
|
||||
render(
|
||||
<SuperChart
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import mockConsole, { RestoreConsole } from 'jest-mock-console';
|
||||
import { ChartProps } from '@superset-ui/core';
|
||||
import { supersetTheme } from '@apache-superset/core/theme';
|
||||
import { render, screen, waitFor } from '@superset-ui/core/spec';
|
||||
@@ -38,10 +37,8 @@ describe('SuperChartCore', () => {
|
||||
new SlowChartPlugin().configure({ key: ChartKeys.SLOW }),
|
||||
];
|
||||
|
||||
let restoreConsole: RestoreConsole;
|
||||
|
||||
beforeAll(() => {
|
||||
jest.setTimeout(30000);
|
||||
vi.setConfig({ testTimeout: 30000 });
|
||||
plugins.forEach(p => {
|
||||
p.unregister().register();
|
||||
});
|
||||
@@ -53,14 +50,6 @@ describe('SuperChartCore', () => {
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
restoreConsole = mockConsole();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
describe('registered charts', () => {
|
||||
test('renders registered chart', async () => {
|
||||
const { container } = render(
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
import { ComponentType } from 'react';
|
||||
import mockConsole, { RestoreConsole } from 'jest-mock-console';
|
||||
import { render as renderTestComponent, screen } from '@testing-library/react';
|
||||
import createLoadableRenderer, {
|
||||
LoadableRenderer as LoadableRendererType,
|
||||
@@ -29,21 +28,19 @@ describe('createLoadableRenderer', () => {
|
||||
function TestComponent() {
|
||||
return <div className="test-component">test</div>;
|
||||
}
|
||||
let loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent));
|
||||
let loadChartSuccess = vi.fn(() => Promise.resolve(TestComponent));
|
||||
let render: (loaded: { Chart: ComponentType }) => JSX.Element;
|
||||
let loading: () => JSX.Element;
|
||||
let LoadableRenderer: LoadableRendererType<{}>;
|
||||
let restoreConsole: RestoreConsole;
|
||||
|
||||
beforeEach(() => {
|
||||
restoreConsole = mockConsole();
|
||||
loadChartSuccess = jest.fn(() => Promise.resolve(TestComponent));
|
||||
render = jest.fn(loaded => {
|
||||
loadChartSuccess = vi.fn(() => Promise.resolve(TestComponent));
|
||||
render = vi.fn(loaded => {
|
||||
const { Chart } = loaded;
|
||||
|
||||
return <Chart />;
|
||||
});
|
||||
loading = jest.fn(() => <div>Loading</div>);
|
||||
loading = vi.fn(() => <div>Loading</div>);
|
||||
|
||||
LoadableRenderer = createLoadableRenderer({
|
||||
loader: {
|
||||
@@ -54,10 +51,6 @@ describe('createLoadableRenderer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
describe('returns a LoadableRenderer class', () => {
|
||||
test('LoadableRenderer.preload() preloads the lazy-load components', () => {
|
||||
expect(LoadableRenderer.preload).toBeInstanceOf(Function);
|
||||
@@ -66,8 +59,8 @@ describe('createLoadableRenderer', () => {
|
||||
});
|
||||
|
||||
test('calls onRenderSuccess when succeeds', async () => {
|
||||
const onRenderSuccess = jest.fn();
|
||||
const onRenderFailure = jest.fn();
|
||||
const onRenderSuccess = vi.fn();
|
||||
const onRenderFailure = vi.fn();
|
||||
renderTestComponent(
|
||||
<LoadableRenderer
|
||||
onRenderSuccess={onRenderSuccess}
|
||||
@@ -75,7 +68,7 @@ describe('createLoadableRenderer', () => {
|
||||
/>,
|
||||
);
|
||||
expect(loadChartSuccess).toHaveBeenCalled();
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
await new Promise(resolve => setTimeout(resolve, 10));
|
||||
expect(render).toHaveBeenCalledTimes(1);
|
||||
expect(onRenderSuccess).toHaveBeenCalledTimes(1);
|
||||
@@ -84,7 +77,7 @@ describe('createLoadableRenderer', () => {
|
||||
|
||||
test('calls onRenderFailure when fails', () =>
|
||||
new Promise(done => {
|
||||
const loadChartFailure = jest.fn(() =>
|
||||
const loadChartFailure = vi.fn(() =>
|
||||
Promise.reject(new Error('Invalid chart')),
|
||||
);
|
||||
const FailedRenderer = createLoadableRenderer({
|
||||
@@ -94,8 +87,8 @@ describe('createLoadableRenderer', () => {
|
||||
loading,
|
||||
render,
|
||||
});
|
||||
const onRenderSuccess = jest.fn();
|
||||
const onRenderFailure = jest.fn();
|
||||
const onRenderSuccess = vi.fn();
|
||||
const onRenderFailure = vi.fn();
|
||||
renderTestComponent(
|
||||
<FailedRenderer
|
||||
onRenderSuccess={onRenderSuccess}
|
||||
@@ -113,7 +106,7 @@ describe('createLoadableRenderer', () => {
|
||||
|
||||
test('onRenderFailure is optional', () =>
|
||||
new Promise(done => {
|
||||
const loadChartFailure = jest.fn(() =>
|
||||
const loadChartFailure = vi.fn(() =>
|
||||
Promise.reject(new Error('Invalid chart')),
|
||||
);
|
||||
const FailedRenderer = createLoadableRenderer({
|
||||
|
||||
@@ -25,7 +25,7 @@ import { render, screen } from '@testing-library/react';
|
||||
import { RenderFuncType } from '../../../src/chart/components/reactify';
|
||||
|
||||
describe('reactify(renderFn)', () => {
|
||||
const renderFn: RenderFuncType<{ content?: string }> = jest.fn(
|
||||
const renderFn: RenderFuncType<{ content?: string }> = vi.fn(
|
||||
(element, props) => {
|
||||
const container = element;
|
||||
container.innerHTML = '';
|
||||
@@ -45,7 +45,7 @@ describe('reactify(renderFn)', () => {
|
||||
content: 'ghi',
|
||||
};
|
||||
|
||||
const willUnmountCb = jest.fn();
|
||||
const willUnmountCb = vi.fn();
|
||||
|
||||
const TheChart = reactify(renderFn);
|
||||
const TheChartWithWillUnmountHook = reactify(renderFn, {
|
||||
@@ -127,7 +127,7 @@ describe('reactify(renderFn)', () => {
|
||||
});
|
||||
});
|
||||
test('does not try to render if not mounted', () => {
|
||||
const anotherRenderFn = jest.fn();
|
||||
const anotherRenderFn = vi.fn();
|
||||
const AnotherChart = reactify(anotherRenderFn); // enables valid new AnotherChart() call
|
||||
// @ts-expect-error
|
||||
new AnotherChart({ id: 'test' }).execute();
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
FeatureFlag,
|
||||
LabelsColorMapSource,
|
||||
} from '@superset-ui/core';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
describe('CategoricalColorScale', () => {
|
||||
beforeEach(() => {
|
||||
@@ -64,26 +65,20 @@ describe('CategoricalColorScale', () => {
|
||||
|
||||
describe('.getColor(value, sliceId)', () => {
|
||||
let scale: CategoricalColorScale;
|
||||
let addSliceSpy: jest.SpyInstance<
|
||||
void,
|
||||
[label: string, color: string, sliceId: number, colorScheme?: string]
|
||||
>;
|
||||
let getNextAvailableColorSpy: jest.SpyInstance<
|
||||
string,
|
||||
[currentLabel: string, currentColor: string]
|
||||
>;
|
||||
let addSliceSpy: Mock<typeof scale.labelsColorMapInstance.addSlice>;
|
||||
let getNextAvailableColorSpy: Mock<typeof scale.getNextAvailableColor>;
|
||||
|
||||
beforeEach(() => {
|
||||
scale = new CategoricalColorScale(['blue', 'red', 'green']);
|
||||
// Spy on the addSlice method of labelsColorMapInstance
|
||||
addSliceSpy = jest.spyOn(scale.labelsColorMapInstance, 'addSlice');
|
||||
getNextAvailableColorSpy = jest
|
||||
addSliceSpy = vi.spyOn(scale.labelsColorMapInstance, 'addSlice');
|
||||
getNextAvailableColorSpy = vi
|
||||
.spyOn(scale, 'getNextAvailableColor')
|
||||
.mockImplementation(color => color);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test('uses labelsColorMapInstance color map when source is Dashboard, otherwise uses chartLabelsColorMap', () => {
|
||||
@@ -94,9 +89,9 @@ describe('CategoricalColorScale', () => {
|
||||
const chartColorMap = new Map([['testValueChart', 'chartColor']]);
|
||||
const dashboardColorMap = new Map([['testValueDash', 'dashboardColor']]);
|
||||
scale.chartLabelsColorMap = chartColorMap;
|
||||
jest
|
||||
.spyOn(scale.labelsColorMapInstance, 'getColorMap')
|
||||
.mockReturnValue(dashboardColorMap);
|
||||
vi.spyOn(scale.labelsColorMapInstance, 'getColorMap').mockReturnValue(
|
||||
dashboardColorMap,
|
||||
);
|
||||
|
||||
// Test when source is Dashboard
|
||||
scale.labelsColorMapInstance.source = LabelsColorMapSource.Dashboard;
|
||||
@@ -406,7 +401,7 @@ describe('CategoricalColorScale', () => {
|
||||
const scale = new CategoricalColorScale(['blue', 'red', 'green']);
|
||||
|
||||
// Mock or override getColorUsageCount to return 0 for "blue"
|
||||
jest.spyOn(scale, 'getColorUsageCount').mockImplementation(color => {
|
||||
vi.spyOn(scale, 'getColorUsageCount').mockImplementation(color => {
|
||||
if (color === 'blue') return 0; // Explicitly return 0 for "blue"
|
||||
return 1; // Return 1 for other colors
|
||||
});
|
||||
|
||||
@@ -27,9 +27,10 @@ import {
|
||||
LabelsColorMap,
|
||||
} from '@superset-ui/core';
|
||||
|
||||
const actual = jest.requireActual('../../src/color/utils');
|
||||
const getAnalogousColorsSpy = jest
|
||||
.spyOn(actual, 'getAnalogousColors')
|
||||
import * as colorUtils from '../../src/color/utils';
|
||||
|
||||
const getAnalogousColorsSpy = vi
|
||||
.spyOn(colorUtils, 'getAnalogousColors')
|
||||
.mockImplementation(() => ['red', 'green', 'blue']);
|
||||
|
||||
describe('LabelsColorMap', () => {
|
||||
@@ -141,8 +142,8 @@ describe('LabelsColorMap', () => {
|
||||
labelsColorMap = getLabelsColorMap();
|
||||
categoricalNamespace = CategoricalColorNamespace.getNamespace(undefined);
|
||||
mockedNamespace = {
|
||||
getScale: jest.fn().mockReturnValue({
|
||||
getColor: jest.fn(() => 'mockColor'),
|
||||
getScale: vi.fn().mockReturnValue({
|
||||
getColor: vi.fn(() => 'mockColor'),
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -25,18 +25,14 @@ import { SupersetTheme, ThemeProvider } from '@apache-superset/core/theme';
|
||||
import AsyncIcon from '../../../src/components/Icons/AsyncIcon';
|
||||
|
||||
// Mock only the SVG import to prevent dynamic import issues
|
||||
jest.mock(
|
||||
'!!@svgr/webpack!../../../src/assets/images/icons/slack.svg',
|
||||
() => {
|
||||
const MockSlackSVG = (props: any) => (
|
||||
<svg {...props} viewBox="0 0 24 24" data-testid="slack-svg">
|
||||
<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52z" />
|
||||
</svg>
|
||||
);
|
||||
return { default: MockSlackSVG };
|
||||
},
|
||||
{ virtual: true },
|
||||
);
|
||||
vi.mock('!!@svgr/webpack!../../../src/assets/images/icons/slack.svg', () => {
|
||||
const MockSlackSVG = (props: any) => (
|
||||
<svg {...props} viewBox="0 0 24 24" data-testid="slack-svg">
|
||||
<path d="M5.042 15.165a2.528 2.528 0 0 1-2.52 2.523A2.528 2.528 0 0 1 0 15.165a2.527 2.527 0 0 1 2.522-2.52h2.52v2.52z" />
|
||||
</svg>
|
||||
);
|
||||
return { default: MockSlackSVG };
|
||||
});
|
||||
|
||||
// Basic theme for testing
|
||||
const mockTheme: SupersetTheme = {
|
||||
@@ -82,7 +78,7 @@ describe('AsyncIcon Integration Tests (Real Component)', () => {
|
||||
});
|
||||
|
||||
test('should set role to button when onClick is provided in real component', () => {
|
||||
const onClick = jest.fn();
|
||||
const onClick = vi.fn();
|
||||
const { container } = render(
|
||||
<ThemeProvider theme={mockTheme}>
|
||||
<AsyncIcon
|
||||
|
||||
@@ -25,7 +25,7 @@ import {
|
||||
/**
|
||||
* NOTE: react-markdown is mocked globally in spec/helpers/shim.tsx (line 89)
|
||||
* to return children as-is without processing. This is intentional to avoid
|
||||
* ESM parsing issues with hast-* packages in Jest.
|
||||
* ESM parsing issues with hast-* packages in vi.
|
||||
*
|
||||
* These tests verify that the SafeMarkdown component renders without errors,
|
||||
* which is the main goal: ensuring remark-gfm v4+ doesn't break the component
|
||||
|
||||
@@ -73,18 +73,18 @@ describe('SupersetClient', () => {
|
||||
fetchMock.put(mockPutUrl, mockPutPayload);
|
||||
fetchMock.get(mockRequestUrl, mockGetPayload);
|
||||
|
||||
const initSpy = jest.spyOn(SupersetClientClass.prototype, 'init');
|
||||
const getSpy = jest.spyOn(SupersetClientClass.prototype, 'get');
|
||||
const postSpy = jest.spyOn(SupersetClientClass.prototype, 'post');
|
||||
const putSpy = jest.spyOn(SupersetClientClass.prototype, 'put');
|
||||
const deleteSpy = jest.spyOn(SupersetClientClass.prototype, 'delete');
|
||||
const authenticatedSpy = jest.spyOn(
|
||||
const initSpy = vi.spyOn(SupersetClientClass.prototype, 'init');
|
||||
const getSpy = vi.spyOn(SupersetClientClass.prototype, 'get');
|
||||
const postSpy = vi.spyOn(SupersetClientClass.prototype, 'post');
|
||||
const putSpy = vi.spyOn(SupersetClientClass.prototype, 'put');
|
||||
const deleteSpy = vi.spyOn(SupersetClientClass.prototype, 'delete');
|
||||
const authenticatedSpy = vi.spyOn(
|
||||
SupersetClientClass.prototype,
|
||||
'isAuthenticated',
|
||||
);
|
||||
const csrfSpy = jest.spyOn(SupersetClientClass.prototype, 'fetchCSRFToken');
|
||||
const requestSpy = jest.spyOn(SupersetClientClass.prototype, 'request');
|
||||
const getGuestTokenSpy = jest.spyOn(
|
||||
const csrfSpy = vi.spyOn(SupersetClientClass.prototype, 'fetchCSRFToken');
|
||||
const requestSpy = vi.spyOn(SupersetClientClass.prototype, 'request');
|
||||
const getGuestTokenSpy = vi.spyOn(
|
||||
SupersetClientClass.prototype,
|
||||
'getGuestToken',
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
import fetchMock from 'fetch-mock';
|
||||
import { SupersetClientClass, ClientConfig, CallApi } from '@superset-ui/core';
|
||||
import { LOGIN_GLOB } from './fixtures/constants';
|
||||
import { Mock } from 'vitest';
|
||||
|
||||
beforeAll(() => fetchMock.mockGlobal());
|
||||
afterAll(() => fetchMock.hardReset());
|
||||
@@ -329,7 +330,7 @@ describe('SupersetClientClass', () => {
|
||||
test('checks for authentication before every get and post request', async () => {
|
||||
expect.assertions(6);
|
||||
|
||||
const authSpy = jest.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
const authSpy = vi.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
const client = new SupersetClientClass({ protocol, host });
|
||||
|
||||
await client.init();
|
||||
@@ -554,7 +555,7 @@ describe('SupersetClientClass', () => {
|
||||
|
||||
describe('when unauthorized', () => {
|
||||
let originalLocation: any;
|
||||
let authSpy: jest.SpyInstance;
|
||||
let authSpy: Mock;
|
||||
const mockRequestUrl = 'https://host/get/url';
|
||||
const mockRequestPath = '/get/url';
|
||||
const mockRequestSearch = '?param=1¶m=2';
|
||||
@@ -569,9 +570,9 @@ describe('SupersetClientClass', () => {
|
||||
search: mockRequestSearch,
|
||||
href: mockHref,
|
||||
} as unknown as Location;
|
||||
authSpy = jest
|
||||
authSpy = vi
|
||||
.spyOn(SupersetClientClass.prototype, 'ensureAuth')
|
||||
.mockImplementation();
|
||||
.mockImplementation(vi.fn());
|
||||
const rejectValue = { status: 401 };
|
||||
fetchMock.get(mockRequestUrl, () => Promise.reject(rejectValue));
|
||||
});
|
||||
@@ -635,7 +636,7 @@ describe('SupersetClientClass', () => {
|
||||
});
|
||||
|
||||
test('accepts an unauthorizedHandler to override redirect behavior', async () => {
|
||||
const unauthorizedHandler = jest.fn();
|
||||
const unauthorizedHandler = vi.fn();
|
||||
const client = new SupersetClientClass({ unauthorizedHandler });
|
||||
|
||||
let error;
|
||||
@@ -663,7 +664,7 @@ describe('SupersetClientClass', () => {
|
||||
const guestToken = 'test-guest-token';
|
||||
const postFormPayload = { number: 123, array: [1, 2, 3] };
|
||||
|
||||
let authSpy: jest.SpyInstance;
|
||||
let authSpy: Mock;
|
||||
let client: SupersetClientClass;
|
||||
let appendChild: any;
|
||||
let removeChild: any;
|
||||
@@ -675,13 +676,13 @@ describe('SupersetClientClass', () => {
|
||||
fetchMock.get(LOGIN_GLOB, { result: 1234 }, { name: LOGIN_GLOB });
|
||||
|
||||
client = new SupersetClientClass({ protocol, host });
|
||||
authSpy = jest.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
authSpy = vi.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
await client.init();
|
||||
appendChild = jest.fn();
|
||||
removeChild = jest.fn();
|
||||
submit = jest.fn();
|
||||
createElement = jest.fn(() => ({
|
||||
appendChild: jest.fn(),
|
||||
appendChild = vi.fn();
|
||||
removeChild = vi.fn();
|
||||
submit = vi.fn();
|
||||
createElement = vi.fn(() => ({
|
||||
appendChild: vi.fn(),
|
||||
submit,
|
||||
}));
|
||||
|
||||
@@ -691,7 +692,7 @@ describe('SupersetClientClass', () => {
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.restoreAllMocks();
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
test.each(['', '/prefix'])(
|
||||
@@ -699,7 +700,7 @@ describe('SupersetClientClass', () => {
|
||||
async appRoot => {
|
||||
if (appRoot !== '') {
|
||||
client = new SupersetClientClass({ protocol, host, appRoot });
|
||||
authSpy = jest.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
authSpy = vi.spyOn(SupersetClientClass.prototype, 'ensureAuth');
|
||||
await client.init();
|
||||
}
|
||||
await client.postForm(mockPostFormEndpoint, {});
|
||||
|
||||
@@ -207,7 +207,7 @@ describe('callApi()', () => {
|
||||
// corruptObject has no toString method and will fail cast to String()
|
||||
corrupt: [corruptObject],
|
||||
};
|
||||
jest.spyOn(console, 'error').mockImplementation();
|
||||
vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
await callApi({
|
||||
url: mockPostUrl,
|
||||
|
||||
@@ -40,12 +40,12 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.removeRoutes().clearHistory();
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
describe('callApi', () => {
|
||||
test('calls callApi()', () => {
|
||||
const callApiSpy = jest.spyOn(callApi, 'default');
|
||||
const callApiSpy = vi.spyOn(callApi, 'default');
|
||||
callApiAndParseWithTimeout({ url: mockGetUrl, method: 'GET' });
|
||||
|
||||
expect(callApiSpy).toHaveBeenCalledTimes(1);
|
||||
@@ -55,7 +55,7 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
|
||||
describe('parseResponse', () => {
|
||||
test('calls parseResponse()', async () => {
|
||||
const parseSpy = jest.spyOn(parseResponse, 'default');
|
||||
const parseSpy = vi.spyOn(parseResponse, 'default');
|
||||
|
||||
await callApiAndParseWithTimeout({
|
||||
url: mockGetUrl,
|
||||
@@ -69,7 +69,7 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
|
||||
describe('timeout', () => {
|
||||
test('does not create a rejection timer if no timeout passed', () => {
|
||||
const rejectionSpy = jest.spyOn(rejectAfterTimeout, 'default');
|
||||
const rejectionSpy = vi.spyOn(rejectAfterTimeout, 'default');
|
||||
callApiAndParseWithTimeout({ url: mockGetUrl, method: 'GET' });
|
||||
|
||||
expect(rejectionSpy).toHaveBeenCalledTimes(0);
|
||||
@@ -77,8 +77,8 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
});
|
||||
|
||||
test('creates a rejection timer if a timeout passed', () => {
|
||||
jest.useFakeTimers(); // prevents the timeout from rejecting + failing test
|
||||
const rejectionSpy = jest.spyOn(rejectAfterTimeout, 'default');
|
||||
vi.useFakeTimers(); // prevents the timeout from rejecting + failing test
|
||||
const rejectionSpy = vi.spyOn(rejectAfterTimeout, 'default');
|
||||
callApiAndParseWithTimeout({
|
||||
url: mockGetUrl,
|
||||
method: 'GET',
|
||||
@@ -91,7 +91,7 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
|
||||
test('rejects if the request exceeds the timeout', async () => {
|
||||
expect.assertions(2);
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
const mockTimeoutUrl = '/mock/timeout/url';
|
||||
const unresolvingPromise = new Promise(() => {});
|
||||
@@ -104,7 +104,7 @@ describe('callApiAndParseWithTimeout()', () => {
|
||||
method: 'GET',
|
||||
timeout: 1,
|
||||
});
|
||||
jest.advanceTimersByTime(2);
|
||||
vi.advanceTimersByTime(2);
|
||||
await promise;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
|
||||
@@ -21,18 +21,18 @@ import rejectAfterTimeout from '../../../src/connection/callApi/rejectAfterTimeo
|
||||
describe('rejectAfterTimeout()', () => {
|
||||
test('returns a promise that rejects after the specified timeout', async () => {
|
||||
expect.assertions(1);
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
let error;
|
||||
|
||||
try {
|
||||
const promise = rejectAfterTimeout(10);
|
||||
jest.advanceTimersByTime(11);
|
||||
vi.advanceTimersByTime(11);
|
||||
await promise;
|
||||
} catch (err) {
|
||||
error = err;
|
||||
} finally {
|
||||
expect(error).toBeDefined();
|
||||
}
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -233,7 +233,7 @@ test('CurrencyFormatter AUTO mode returns plain value when getCurrencySymbol ret
|
||||
|
||||
const OrigNumberFormat = Intl.NumberFormat;
|
||||
// Return formatToParts without a 'currency' entry so getCurrencySymbol → undefined
|
||||
Intl.NumberFormat = jest.fn().mockImplementation(() => ({
|
||||
Intl.NumberFormat = vi.fn().mockImplementation(() => ({
|
||||
formatToParts: () => [{ type: 'integer', value: '1' }],
|
||||
})) as unknown as typeof Intl.NumberFormat;
|
||||
|
||||
@@ -254,7 +254,7 @@ test('CurrencyFormatter AUTO mode falls back to plain value when getCurrencySymb
|
||||
// Mock Intl.NumberFormat to throw to simulate an environment where the
|
||||
// currency code is rejected, triggering the catch block in format()
|
||||
const OrigNumberFormat = Intl.NumberFormat;
|
||||
Intl.NumberFormat = jest.fn().mockImplementation(() => {
|
||||
Intl.NumberFormat = vi.fn().mockImplementation(() => {
|
||||
throw new RangeError('Invalid currency code');
|
||||
}) as unknown as typeof Intl.NumberFormat;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ describe('LazyFactory', () => {
|
||||
expect(innerDiv.parentNode).toEqual(div);
|
||||
});
|
||||
test('reuses existing', () => {
|
||||
const factoryFn = jest.fn(() => document.createElement('div'));
|
||||
const factoryFn = vi.fn(() => document.createElement('div'));
|
||||
const factory = new LazyFactory(factoryFn);
|
||||
const div1 = factory.createInContainer();
|
||||
const div2 = factory.createInContainer();
|
||||
|
||||
@@ -26,7 +26,7 @@ describe('shared modules', () => {
|
||||
|
||||
test('assigns to window', async () => {
|
||||
const fakeModule = { foo: 'bar' };
|
||||
const fetchModule = jest.fn().mockResolvedValue(fakeModule);
|
||||
const fetchModule = vi.fn().mockResolvedValue(fakeModule);
|
||||
|
||||
await defineSharedModule('test-module', fetchModule);
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('shared modules', () => {
|
||||
|
||||
test('resolves to the same reference every time', async () => {
|
||||
const fakeModule = { foo: 'bar' };
|
||||
const fetchModule = jest.fn().mockResolvedValue(fakeModule);
|
||||
const fetchModule = vi.fn().mockResolvedValue(fakeModule);
|
||||
|
||||
const result1 = await defineSharedModule('test-module', fetchModule);
|
||||
const result2 = await defineSharedModule('test-module', fetchModule);
|
||||
@@ -48,8 +48,8 @@ describe('shared modules', () => {
|
||||
|
||||
test('does not redefine unnecessarily', async () => {
|
||||
const fakeModule = { foo: 'bar' };
|
||||
const fetchModule = jest.fn().mockResolvedValue(fakeModule);
|
||||
const duplicateFetchModule = jest.fn().mockResolvedValue(fakeModule);
|
||||
const fetchModule = vi.fn().mockResolvedValue(fakeModule);
|
||||
const duplicateFetchModule = vi.fn().mockResolvedValue(fakeModule);
|
||||
|
||||
const result1 = await defineSharedModule('test-module', fetchModule);
|
||||
const result2 = await defineSharedModule(
|
||||
@@ -65,7 +65,7 @@ describe('shared modules', () => {
|
||||
test('deduplicates in-progress definitions', async () => {
|
||||
const fakeModule = { foo: 'bar' };
|
||||
// get a promise that actually takes a moment;
|
||||
const fetchModule = jest
|
||||
const fetchModule = vi
|
||||
.fn()
|
||||
.mockImplementation(() =>
|
||||
Promise.resolve(setImmediate).then(() => fakeModule),
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* eslint no-console: 0 */
|
||||
import mockConsole from 'jest-mock-console';
|
||||
import { Registry, OverwritePolicy } from '@superset-ui/core';
|
||||
|
||||
const loader = () => 'testValue';
|
||||
|
||||
const consoleWarnSpy = vi.spyOn(console, 'warn');
|
||||
const consoleErrorSpy = vi.spyOn(console, 'error');
|
||||
|
||||
describe('Registry', () => {
|
||||
test('exists', () => {
|
||||
expect(Registry !== undefined).toBe(true);
|
||||
@@ -308,33 +309,28 @@ describe('Registry', () => {
|
||||
describe('=ALLOW', () => {
|
||||
describe('.registerValue(key, value)', () => {
|
||||
test('registers normally', () => {
|
||||
const restoreConsole = mockConsole();
|
||||
const registry = new Registry();
|
||||
registry.registerValue('a', 'testValue');
|
||||
expect(() => registry.registerValue('a', 'testValue2')).not.toThrow();
|
||||
expect(registry.get('a')).toEqual('testValue2');
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
restoreConsole();
|
||||
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('.registerLoader(key, loader)', () => {
|
||||
test('registers normally', () => {
|
||||
const restoreConsole = mockConsole();
|
||||
const registry = new Registry();
|
||||
registry.registerLoader('a', () => 'testValue');
|
||||
expect(() =>
|
||||
registry.registerLoader('a', () => 'testValue2'),
|
||||
).not.toThrow();
|
||||
expect(registry.get('a')).toEqual('testValue2');
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
restoreConsole();
|
||||
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('=WARN', () => {
|
||||
describe('.registerValue(key, value)', () => {
|
||||
test('warns when overwrite', () => {
|
||||
const restoreConsole = mockConsole();
|
||||
const registry = new Registry({
|
||||
overwritePolicy: OverwritePolicy.Warn,
|
||||
});
|
||||
@@ -342,12 +338,10 @@ describe('Registry', () => {
|
||||
expect(() => registry.registerValue('a', 'testValue2')).not.toThrow();
|
||||
expect(registry.get('a')).toEqual('testValue2');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
restoreConsole();
|
||||
});
|
||||
});
|
||||
describe('.registerLoader(key, loader)', () => {
|
||||
test('warns when overwrite', () => {
|
||||
const restoreConsole = mockConsole();
|
||||
const registry = new Registry({
|
||||
overwritePolicy: OverwritePolicy.Warn,
|
||||
});
|
||||
@@ -356,8 +350,7 @@ describe('Registry', () => {
|
||||
registry.registerLoader('a', () => 'testValue2'),
|
||||
).not.toThrow();
|
||||
expect(registry.get('a')).toEqual('testValue2');
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
restoreConsole();
|
||||
expect(consoleWarnSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -387,10 +380,10 @@ describe('Registry', () => {
|
||||
|
||||
describe('listeners', () => {
|
||||
let registry = new Registry();
|
||||
let listener = jest.fn();
|
||||
let listener = vi.fn();
|
||||
beforeEach(() => {
|
||||
registry = new Registry();
|
||||
listener = jest.fn();
|
||||
listener = vi.fn();
|
||||
registry.addListener(listener);
|
||||
});
|
||||
|
||||
@@ -438,19 +431,11 @@ describe('Registry', () => {
|
||||
});
|
||||
|
||||
describe('with a broken listener', () => {
|
||||
let restoreConsole: any;
|
||||
beforeEach(() => {
|
||||
restoreConsole = mockConsole();
|
||||
});
|
||||
afterEach(() => {
|
||||
restoreConsole();
|
||||
});
|
||||
|
||||
test('keeps working', () => {
|
||||
const errorListener = jest.fn().mockImplementation(() => {
|
||||
const errorListener = vi.fn().mockImplementation(() => {
|
||||
throw new Error('test error');
|
||||
});
|
||||
const lastListener = jest.fn();
|
||||
const lastListener = vi.fn();
|
||||
|
||||
registry.addListener(errorListener);
|
||||
registry.addListener(lastListener);
|
||||
@@ -459,7 +444,7 @@ describe('Registry', () => {
|
||||
expect(listener).toHaveBeenCalledWith(['foo']);
|
||||
expect(errorListener).toHaveBeenCalledWith(['foo']);
|
||||
expect(lastListener).toHaveBeenCalledWith(['foo']);
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
expect(consoleErrorSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -47,7 +47,7 @@ describe('makeApi()', () => {
|
||||
});
|
||||
const client = new SupersetClientClass({ appRoot: '/foo' });
|
||||
const mockResponse = { yes: 'ok' };
|
||||
const mockRequest = jest.fn(() =>
|
||||
const mockRequest = vi.fn(() =>
|
||||
Promise.resolve(
|
||||
new Response(JSON.stringify(mockResponse), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
|
||||
@@ -125,10 +125,7 @@ describe('buildQueryContext', () => {
|
||||
]);
|
||||
});
|
||||
test('should call normalizeTimeColumn if has x_axis', () => {
|
||||
const spyNormalizeTimeColumn = jest.spyOn(
|
||||
queryModule,
|
||||
'normalizeTimeColumn',
|
||||
);
|
||||
const spyNormalizeTimeColumn = vi.spyOn(queryModule, 'normalizeTimeColumn');
|
||||
|
||||
buildQueryContext(
|
||||
{
|
||||
|
||||
@@ -23,12 +23,12 @@ const TODAY = '2024-06-03';
|
||||
|
||||
// Mock Date to always return 2024-06-03
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
jest.setSystemTime(new Date(TODAY).getTime());
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date(TODAY).getTime());
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
test('should return the current date for "now"', () => {
|
||||
|
||||
@@ -27,7 +27,7 @@ const NOW_UTC_IN_PACIFIC = '2024-06-03T08:00:00Z'; // Same as 2024-06-03T00:00:0
|
||||
|
||||
afterEach(() => {
|
||||
timezoneMock.unregister();
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
const runTimezoneTest = (
|
||||
@@ -40,7 +40,7 @@ const runTimezoneTest = (
|
||||
includeFutureOffsets = true,
|
||||
) => {
|
||||
timezoneMock.register(timezone);
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
vi.setSystemTime(new Date(now_time));
|
||||
const result = getTimeOffset({
|
||||
timeRangeFilter,
|
||||
shifts,
|
||||
@@ -52,9 +52,9 @@ const runTimezoneTest = (
|
||||
};
|
||||
|
||||
test('should handle includeFutureOffsets is null', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
timezoneMock.register('Etc/GMT-2');
|
||||
jest.setSystemTime(new Date(NOW_UTC_IN_EUROPE));
|
||||
vi.setSystemTime(new Date(NOW_UTC_IN_EUROPE));
|
||||
const result = getTimeOffset({
|
||||
timeRangeFilter: {
|
||||
comparator: '2024-06-03 : 2024-06-10',
|
||||
@@ -72,7 +72,7 @@ test('should handle custom range with specific dates', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -101,7 +101,7 @@ test('should handle custom range with relative dates (now)', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-30';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -130,7 +130,7 @@ test('should handle inherit shift', () => {
|
||||
};
|
||||
const shifts = ['inherit'];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -158,7 +158,7 @@ test('should handle custom and inherit shifts', () => {
|
||||
};
|
||||
const shifts = ['custom', 'inherit'];
|
||||
const startDate = '2024-05-28';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -187,7 +187,7 @@ test('should handle no shifts', () => {
|
||||
};
|
||||
const shifts: any = [];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -211,7 +211,7 @@ test('should handle null timeRangeFilter', () => {
|
||||
const timeRangeFilter = null;
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-06-01';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -239,7 +239,7 @@ test('should handle predefined shifts', () => {
|
||||
};
|
||||
const shifts: any = ['1 year ago'];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -269,7 +269,7 @@ test('should handle custom range with DATEADD function', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-21';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -297,7 +297,7 @@ test('should handle custom range with DATEADD function and relative start date',
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-06-01';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -325,7 +325,7 @@ test('should handle custom range with DATEADD function and relative end date', (
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-23';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -354,7 +354,7 @@ test('should handle custom range with specific date and relative end date', () =
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-23';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -383,7 +383,7 @@ test('should handle custom range with specific date and specific end date', () =
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-06-01';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -411,7 +411,7 @@ test('should handle custom range with Last and now', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-30';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -439,7 +439,7 @@ test('should handle custom range with Last week', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-21';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -467,7 +467,7 @@ test('should handle custom range with previous calendar week', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-26';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024-06-05T02:06:00+02:00',
|
||||
'Etc/GMT-2',
|
||||
@@ -500,7 +500,7 @@ test('should handle custom range with previous calendar month', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-04-26';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024-06-05T02:06:00+02:00',
|
||||
'Etc/GMT-2',
|
||||
@@ -533,7 +533,7 @@ test('should handle custom range with previous calendar year', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2022-12-26';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
'2024-06-05T02:06:00+02:00',
|
||||
@@ -567,7 +567,7 @@ test('should handle custom range with Advanced 2022-11-01', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2022-10-18';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
'2024-06-05T02:06:00+02:00',
|
||||
@@ -601,7 +601,7 @@ test('should handle future inherit shift with includeFutureOffsets set to true',
|
||||
};
|
||||
const shifts = ['inherit'];
|
||||
const startDate = '2024-06-20';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -638,7 +638,7 @@ test('should handle future custom shift with includeFutureOffsets set to true',
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-06-15';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -667,7 +667,7 @@ test('should handle custom range with specific (YYYY-MM) and relative dates', ()
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -696,7 +696,7 @@ test('should handle custom range with minutes', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -725,7 +725,7 @@ test('should handle custom range with undefined startDate', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = undefined;
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -752,7 +752,7 @@ test('should handle future custom shift with different format', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-06-15';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -782,7 +782,7 @@ test('should handle custom range with relative dates', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -812,7 +812,7 @@ test('should handle custom range with relative dates (minute and seconds)', () =
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -842,7 +842,7 @@ test('should handle custom range with relative dates (hour)', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -871,7 +871,7 @@ test('should handle custom shifts with same day', () => {
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -900,7 +900,7 @@ test('should handle inherit shifts without filter', () => {
|
||||
};
|
||||
const shifts = ['inherit'];
|
||||
const startDate = '2024-05-29';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -927,7 +927,7 @@ test('should handle inherit shift same day', () => {
|
||||
};
|
||||
const shifts = ['inherit'];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -963,7 +963,7 @@ test('should handle inherit shift same day includeFutureOffsets set to false', (
|
||||
};
|
||||
const shifts = ['inherit'];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
@@ -999,7 +999,7 @@ test('should handle custom shift same day includeFutureOffsets set to false', ()
|
||||
};
|
||||
const shifts = ['custom'];
|
||||
const startDate = '2024-03-06';
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
NOW_UTC_IN_EUROPE,
|
||||
'Etc/GMT-2',
|
||||
|
||||
@@ -27,7 +27,7 @@ const NOW_UTC_IN_PACIFIC = '2024-06-03T08:00:00Z'; // Same as 2024-06-03T00:00:0
|
||||
|
||||
afterEach(() => {
|
||||
timezoneMock.unregister();
|
||||
jest.useRealTimers();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
const runTimezoneTest = (
|
||||
@@ -39,7 +39,7 @@ const runTimezoneTest = (
|
||||
computingShift = false,
|
||||
) => {
|
||||
timezoneMock.register(timezone);
|
||||
jest.setSystemTime(new Date(now_time));
|
||||
vi.setSystemTime(new Date(now_time));
|
||||
expect(parseDttmToDate(eval_time, endDate, computingShift)).toEqual(
|
||||
expected_result,
|
||||
);
|
||||
@@ -47,7 +47,7 @@ const runTimezoneTest = (
|
||||
};
|
||||
|
||||
test('should return the current date for "now"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'now',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -64,7 +64,7 @@ test('should return the current date for "now"', () => {
|
||||
});
|
||||
|
||||
test('should return the current date for "today"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'today',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -81,7 +81,7 @@ test('should return the current date for "today"', () => {
|
||||
});
|
||||
|
||||
test('should return the current date for "No filter"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'No filter',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -103,7 +103,7 @@ test('should return the current date for "No filter"', () => {
|
||||
});
|
||||
|
||||
test('should return the current date for an empty string', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -120,7 +120,7 @@ test('should return the current date for an empty string', () => {
|
||||
});
|
||||
|
||||
test('should return yesterday date for "Last day"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last day',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -142,7 +142,7 @@ test('should return yesterday date for "Last day"', () => {
|
||||
});
|
||||
|
||||
test('should return the date one week ago for "Last week"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -164,7 +164,7 @@ test('should return the date one week ago for "Last week"', () => {
|
||||
});
|
||||
|
||||
test('should return the date one month ago for "Last month"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -186,7 +186,7 @@ test('should return the date one month ago for "Last month"', () => {
|
||||
});
|
||||
|
||||
test('should return the date three months ago for "Last quarter"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last quarter',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -208,7 +208,7 @@ test('should return the date three months ago for "Last quarter"', () => {
|
||||
});
|
||||
|
||||
test('should return the date one year ago for "Last year"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -230,7 +230,7 @@ test('should return the date one year ago for "Last year"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar week"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
'2024-06-04T22:00:00Z',
|
||||
@@ -252,7 +252,7 @@ test('should return the date for "previous calendar week"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar month"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -274,7 +274,7 @@ test('should return the date for "previous calendar month"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar year"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -296,7 +296,7 @@ test('should return the date for "previous calendar year"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "1 day ago"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'1 day ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -318,7 +318,7 @@ test('should return the date for "1 day ago"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "1 week ago"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'1 week ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -340,7 +340,7 @@ test('should return the date for "1 week ago"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "1 month ago"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'1 month ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -362,7 +362,7 @@ test('should return the date for "1 month ago"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "1 year ago"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'1 year ago',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -384,7 +384,7 @@ test('should return the date for "1 year ago"', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "2024-03-09"', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024-03-09',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -406,7 +406,7 @@ test('should return the date for "2024-03-09"', () => {
|
||||
});
|
||||
|
||||
test('should return the current date for "Last day" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last day',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -431,7 +431,7 @@ test('should return the current date for "Last day" with isEndDate true', () =>
|
||||
});
|
||||
|
||||
test('should return the current date for "Last week" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -456,7 +456,7 @@ test('should return the current date for "Last week" with isEndDate true', () =>
|
||||
});
|
||||
|
||||
test('should return the current date for "Last quarter" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last quarter',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -481,7 +481,7 @@ test('should return the current date for "Last quarter" with isEndDate true', ()
|
||||
});
|
||||
|
||||
test('should return the current date for "Last year" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'Last year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -506,7 +506,7 @@ test('should return the current date for "Last year" with isEndDate true', () =>
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar week" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar week',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -531,7 +531,7 @@ test('should return the date for "previous calendar week" with isEndDate true',
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar month" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar month',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -556,7 +556,7 @@ test('should return the date for "previous calendar month" with isEndDate true',
|
||||
});
|
||||
|
||||
test('should return the date for "previous calendar year" with isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'previous calendar year',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -581,7 +581,7 @@ test('should return the date for "previous calendar year" with isEndDate true',
|
||||
});
|
||||
|
||||
test('should return the date for "2024" with parts.length === 1', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -598,7 +598,7 @@ test('should return the date for "2024" with parts.length === 1', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "2024-03" with parts.length === 2', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024-03',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -620,7 +620,7 @@ test('should return the date for "2024-03" with parts.length === 2', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "2024-03-06" with parts.length === 3', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
runTimezoneTest(
|
||||
'2024-03-06',
|
||||
NOW_UTC_IN_EUROPE,
|
||||
@@ -642,7 +642,7 @@ test('should return the date for "2024-03-06" with parts.length === 3', () => {
|
||||
});
|
||||
|
||||
test('should return the date for "2024-03-06" with computingShifts true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
const expectedDate = new Date('2024-03-05T22:00:00Z');
|
||||
expectedDate.setHours(-expectedDate.getTimezoneOffset() / 60, 0, 0, 0);
|
||||
runTimezoneTest(
|
||||
@@ -656,7 +656,7 @@ test('should return the date for "2024-03-06" with computingShifts true', () =>
|
||||
});
|
||||
|
||||
test('should return the date for "2024-03-06" with computingShifts true and isEndDate true', () => {
|
||||
jest.useFakeTimers();
|
||||
vi.useFakeTimers();
|
||||
const expectedDate = new Date('2024-03-05T22:00:00Z');
|
||||
expectedDate.setHours(-expectedDate.getTimezoneOffset() / 60, 0, 0, 0);
|
||||
runTimezoneTest(
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user