Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from apache:master #1170

Merged
merged 3 commits into from
Aug 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,7 @@
*/
import React from 'react';
import * as reactRedux from 'react-redux';
import {
render,
screen,
waitFor,
within,
cleanup,
} from 'spec/helpers/testing-library';
import { render, screen, cleanup, waitFor } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import fetchMock from 'fetch-mock';
import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal';
Expand All @@ -43,6 +37,8 @@ fetchMock.get('glob:*/api/v1/dataset?*', {
dataset_count: 3,
});

jest.useFakeTimers();

// Mock the user
const useSelectorMock = jest.spyOn(reactRedux, 'useSelector');
beforeEach(() => {
Expand All @@ -51,7 +47,7 @@ beforeEach(() => {
});

describe('SaveDatasetModal', () => {
it('renders a "Save as new" field', async () => {
it('renders a "Save as new" field', () => {
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

const saveRadioBtn = screen.getByRole('radio', {
Expand All @@ -68,7 +64,7 @@ describe('SaveDatasetModal', () => {
expect(inputFieldText).toBeVisible();
});

it('renders an "Overwrite existing" field', async () => {
it('renders an "Overwrite existing" field', () => {
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

const overwriteRadioBtn = screen.getByRole('radio', {
Expand All @@ -84,20 +80,20 @@ describe('SaveDatasetModal', () => {
expect(placeholderText).toBeVisible();
});

it('renders a close button', async () => {
it('renders a close button', () => {
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

expect(screen.getByRole('button', { name: /close/i })).toBeVisible();
});

it('renders a save button when "Save as new" is selected', async () => {
it('renders a save button when "Save as new" is selected', () => {
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

// "Save as new" is selected when the modal opens by default
expect(screen.getByRole('button', { name: /save/i })).toBeVisible();
});

it('renders an overwrite button when "Overwrite existing" is selected', async () => {
it('renders an overwrite button when "Overwrite existing" is selected', () => {
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

// Click the overwrite radio button to reveal the overwrite confirmation and back buttons
Expand All @@ -109,39 +105,73 @@ describe('SaveDatasetModal', () => {
expect(screen.getByRole('button', { name: /overwrite/i })).toBeVisible();
});

it('renders the overwrite button as disabled until an existing dataset is selected, confirms overwrite', async () => {
it('renders the overwrite button as disabled until an existing dataset is selected', async () => {
useSelectorMock.mockReturnValue({ ...user });
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

// Click the overwrite radio button
const overwriteRadioBtn = screen.getByRole('radio', {
name: /overwrite existing/i,
});
await waitFor(async () => {
userEvent.click(overwriteRadioBtn);
});
userEvent.click(overwriteRadioBtn);

// Overwrite confirmation button should be disabled at this point
const overwriteConfirmationBtn = screen.getByRole('button', {
name: /overwrite/i,
});
expect(overwriteConfirmationBtn).toBeDisabled();

// Click the select component
// Click the overwrite select component
const select = screen.getByRole('combobox', { name: /existing dataset/i })!;
await waitFor(async () => userEvent.click(select));
userEvent.click(select);

await waitFor(() =>
expect(screen.queryByText('Loading...')).not.toBeVisible(),
);

// Select the first "existing dataset" from the listbox
const option = within(
document.querySelector('.rc-virtual-list')!,
).getByText('coolest table 0')!;
const option = screen.getAllByText('coolest table 0')[1];
userEvent.click(option);

// Overwrite button should now be enabled
expect(overwriteConfirmationBtn).toBeEnabled();
});

it('renders a confirm overwrite screen when overwrite is clicked', async () => {
useSelectorMock.mockReturnValue({ ...user });
render(<SaveDatasetModal {...mockedProps} />, { useRedux: true });

// Click the overwrite radio button
const overwriteRadioBtn = screen.getByRole('radio', {
name: /overwrite existing/i,
});
userEvent.click(overwriteRadioBtn);

// Click the overwrite select component
const select = screen.getByRole('combobox', { name: /existing dataset/i });
userEvent.click(select);

await waitFor(() =>
expect(screen.queryByText('Loading...')).not.toBeVisible(),
);

// Select the first "existing dataset" from the listbox
const option = screen.getAllByText('coolest table 0')[1];
userEvent.click(option);

// Check Overwrite confirmation functionality
// Click the overwrite button to access the confirmation screen
const overwriteConfirmationBtn = screen.getByRole('button', {
name: /overwrite/i,
});
userEvent.click(overwriteConfirmationBtn);

// Overwrite screen text
expect(screen.getByText(/save or overwrite dataset/i)).toBeVisible();
expect(
screen.getByText(/are you sure you want to overwrite this dataset\?/i),
).toBeVisible();
// Overwrite screen buttons
expect(screen.getByRole('button', { name: /close/i })).toBeVisible();
expect(screen.getByRole('button', { name: /back/i })).toBeVisible();
expect(screen.getByRole('button', { name: /overwrite/i })).toBeVisible();
});
Expand Down
2 changes: 1 addition & 1 deletion superset/connectors/sqla/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class SqlMetricInlineView( # pylint: disable=too-many-ancestors
add_title = _("Add Metric")
edit_title = _("Edit Metric")

list_columns = ["metric_name", "verbose_name", "metric_type"]
list_columns = ["metric_name", "verbose_name", "metric_type", "extra"]
edit_columns = [
"metric_name",
"description",
Expand Down
2 changes: 1 addition & 1 deletion superset/db_engine_specs/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def convert_dttm(
) -> Optional[str]:
tt = target_type.upper()
if tt in (utils.TemporalType.TEXT, utils.TemporalType.DATETIME):
return f"""'{dttm.isoformat(sep=" ", timespec="microseconds")}'"""
return f"""'{dttm.isoformat(sep=" ", timespec="seconds")}'"""
return None

@classmethod
Expand Down
4 changes: 2 additions & 2 deletions tests/unit_tests/db_engine_specs/test_sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@
def test_convert_dttm(dttm: datetime) -> None:
from superset.db_engine_specs.sqlite import SqliteEngineSpec

assert SqliteEngineSpec.convert_dttm("TEXT", dttm) == "'2019-01-02 03:04:05.678900'"
assert SqliteEngineSpec.convert_dttm("TEXT", dttm) == "'2019-01-02 03:04:05'"


def test_convert_dttm_lower(dttm: datetime) -> None:
from superset.db_engine_specs.sqlite import SqliteEngineSpec

assert SqliteEngineSpec.convert_dttm("text", dttm) == "'2019-01-02 03:04:05.678900'"
assert SqliteEngineSpec.convert_dttm("text", dttm) == "'2019-01-02 03:04:05'"


def test_convert_dttm_invalid_type(dttm: datetime) -> None:
Expand Down