This is an automated email from the ASF dual-hosted git repository.

lyndsi pushed a commit to branch 
lyndsi/sql-lab-new-explore-button-functionality-and-move-save-dataset-to-split-save-button
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 237ca9644580e629a8e669d3deae69bf2982280d
Author: lyndsiWilliams <[email protected]>
AuthorDate: Tue Jun 28 20:10:10 2022 -0500

    Added testing and converted SaveQuery test to RTL
---
 .../SaveDatasetActionButton.test.tsx               |  62 +++++++
 .../SqlLab/components/SaveQuery/SaveQuery.test.jsx | 193 +++++++++++++++------
 .../src/SqlLab/components/SaveQuery/index.tsx      |  39 ++---
 3 files changed, 220 insertions(+), 74 deletions(-)

diff --git 
a/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx
 
b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx
new file mode 100644
index 0000000000..ec129d5a6a
--- /dev/null
+++ 
b/superset-frontend/src/SqlLab/components/SaveDatasetActionButton/SaveDatasetActionButton.test.tsx
@@ -0,0 +1,62 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import React from 'react';
+import { render, screen } from 'spec/helpers/testing-library';
+import userEvent from '@testing-library/user-event';
+import { Menu } from 'src/components/Menu';
+import SaveDatasetActionButton from 
'src/SqlLab/components/SaveDatasetActionButton';
+
+const overlayMenu = (
+  <Menu>
+    <Menu.Item>Save dataset</Menu.Item>
+  </Menu>
+);
+
+describe('SaveDatasetActionButton', () => {
+  it('renders a split save button', () => {
+    render(
+      <SaveDatasetActionButton
+        toggleSave={() => {}}
+        overlayMenu={overlayMenu}
+      />,
+    );
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
+    const caretBtn = screen.getByRole('button', { name: /caret-down/i });
+
+    expect(saveBtn).toBeVisible();
+    expect(caretBtn).toBeVisible();
+  });
+
+  it('renders a "save dataset" dropdown menu item when user clicks caret 
button', () => {
+    render(
+      <SaveDatasetActionButton
+        toggleSave={() => {}}
+        overlayMenu={overlayMenu}
+      />,
+    );
+
+    const caretBtn = screen.getByRole('button', { name: /caret-down/i });
+    userEvent.click(caretBtn);
+
+    const saveDatasetMenuItem = screen.getByText(/save dataset/i);
+
+    expect(saveDatasetMenuItem).toBeInTheDocument();
+  });
+});
diff --git 
a/superset-frontend/src/SqlLab/components/SaveQuery/SaveQuery.test.jsx 
b/superset-frontend/src/SqlLab/components/SaveQuery/SaveQuery.test.jsx
index 76f6ca8260..5d9237dec8 100644
--- a/superset-frontend/src/SqlLab/components/SaveQuery/SaveQuery.test.jsx
+++ b/superset-frontend/src/SqlLab/components/SaveQuery/SaveQuery.test.jsx
@@ -17,60 +17,87 @@
  * under the License.
  */
 import React from 'react';
-import { shallow } from 'enzyme';
-import * as sinon from 'sinon';
+import { render, screen } from 'spec/helpers/testing-library';
+import userEvent from '@testing-library/user-event';
 import SaveQuery from 'src/SqlLab/components/SaveQuery';
-import Modal from 'src/components/Modal';
-import Button from 'src/components/Button';
-import { FormItem } from 'src/components/Form';
+import { databases } from 'src/SqlLab/fixtures';
+
+const mockedProps = {
+  query: {
+    dbId: 1,
+    schema: 'main',
+    sql: 'SELECT * FROM t',
+  },
+  defaultLabel: 'untitled',
+  animation: false,
+  database: databases.result[0],
+  onUpdate: () => {},
+  onSave: () => {},
+};
+
+const splitSaveBtnProps = {
+  ...mockedProps,
+  database: {
+    ...mockedProps.database,
+    allows_virtual_table_explore: true,
+  },
+};
 
 describe('SavedQuery', () => {
-  const mockedProps = {
-    query: {
-      dbId: 1,
-      schema: 'main',
-      sql: 'SELECT * FROM t',
-    },
-    defaultLabel: 'untitled',
-    animation: false,
-  };
-  it('is valid', () => {
-    expect(React.isValidElement(<SaveQuery />)).toBe(true);
-  });
-  it('is valid with props', () => {
-    expect(React.isValidElement(<SaveQuery {...mockedProps} />)).toBe(true);
-  });
-  it('has a Modal', () => {
-    const wrapper = shallow(<SaveQuery {...mockedProps} />);
-    expect(wrapper.find(Modal)).toExist();
-  });
-  // TODO: eschutho convert test to RTL
-  // eslint-disable-next-line jest/no-disabled-tests
-  it.skip('has a cancel button', () => {
-    const wrapper = shallow(<SaveQuery {...mockedProps} />);
-    const modal = wrapper.find(Modal);
+  it('renders a non-split save button when allows_virtual_table_explore is not 
enabled', () => {
+    render(<SaveQuery {...mockedProps} />, { useRedux: true });
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
 
-    expect(modal.find('[data-test="cancel-query"]')).toHaveLength(1);
+    expect(saveBtn).toBeVisible();
   });
-  it('has 2 FormItem', () => {
-    const wrapper = shallow(<SaveQuery {...mockedProps} />);
-    const modal = wrapper.find(Modal);
 
-    expect(modal.find(FormItem)).toHaveLength(2);
+  it('renders a save query modal when user clicks save button', () => {
+    render(<SaveQuery {...mockedProps} />, { useRedux: true });
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
+    userEvent.click(saveBtn);
+
+    const saveQueryModalHeader = screen.getByRole('heading', {
+      name: /save query/i,
+    });
+
+    expect(saveQueryModalHeader).toBeVisible();
   });
-  // eslint-disable-next-line jest/no-disabled-tests
-  it.skip('has a save button if this is a new query', () => {
-    const saveSpy = sinon.spy();
-    const wrapper = shallow(<SaveQuery {...mockedProps} onSave={saveSpy} />);
-    const modal = wrapper.find(Modal);
-
-    expect(modal.find(Button)).toHaveLength(2);
-    modal.find(Button).at(0).simulate('click');
-    expect(saveSpy.calledOnce).toBe(true);
+
+  it('renders the save query modal UI', () => {
+    render(<SaveQuery {...mockedProps} />, { useRedux: true });
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
+    userEvent.click(saveBtn);
+
+    const closeBtn = screen.getByRole('button', { name: /close/i });
+    const saveQueryModalHeader = screen.getByRole('heading', {
+      name: /save query/i,
+    });
+    const nameLabel = screen.getByText(/name/i);
+    const descriptionLabel = screen.getByText(/description/i);
+    const textBoxes = screen.getAllByRole('textbox');
+    const nameTextbox = textBoxes[0];
+    const descriptionTextbox = textBoxes[1];
+    // There are now two save buttons, the initial save button and the modal 
save button
+    const saveBtns = screen.getAllByRole('button', { name: /save/i });
+    const cancelBtn = screen.getByRole('button', { name: /cancel/i });
+
+    expect(closeBtn).toBeVisible();
+    expect(saveQueryModalHeader).toBeVisible();
+    expect(nameLabel).toBeVisible();
+    expect(descriptionLabel).toBeVisible();
+    expect(textBoxes.length).toBe(2);
+    expect(nameTextbox).toBeVisible();
+    expect(descriptionTextbox).toBeVisible();
+    expect(saveBtns.length).toBe(2);
+    expect(saveBtns[0]).toBeVisible();
+    expect(saveBtns[1]).toBeVisible();
+    expect(cancelBtn).toBeVisible();
   });
-  // eslint-disable-next-line jest/no-disabled-tests
-  it.skip('has an update button if this is an existing query', () => {
-    const updateSpy = sinon.spy();
+
+  it('renders a "save as new" and "update" button if query already exists', () 
=> {
     const props = {
       ...mockedProps,
       query: {
@@ -78,11 +105,75 @@ describe('SavedQuery', () => {
         remoteId: '42',
       },
     };
-    const wrapper = shallow(<SaveQuery {...props} onUpdate={updateSpy} />);
-    const modal = wrapper.find(Modal);
+    render(<SaveQuery {...props} />, { useRedux: true });
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
+    userEvent.click(saveBtn);
+
+    const saveAsNewBtn = screen.getByRole('button', { name: /save as new/i });
+    const updateBtn = screen.getByRole('button', { name: /update/i });
+
+    expect(saveAsNewBtn).toBeVisible();
+    expect(updateBtn).toBeVisible();
+  });
+
+  it('renders a split save button when allows_virtual_table_explore is 
enabled', () => {
+    render(<SaveQuery {...splitSaveBtnProps} />, { useRedux: true });
+
+    const saveBtn = screen.getByRole('button', { name: /save/i });
+    const caretBtn = screen.getByRole('button', { name: /caret-down/i });
+
+    expect(saveBtn).toBeVisible();
+    expect(caretBtn).toBeVisible();
+  });
+
+  it('renders a save dataset modal when user clicks "save dataset" menu item', 
() => {
+    render(<SaveQuery {...splitSaveBtnProps} />, { useRedux: true });
+
+    const caretBtn = screen.getByRole('button', { name: /caret-down/i });
+    userEvent.click(caretBtn);
+
+    const saveDatasetMenuItem = screen.getByText(/save dataset/i);
+    userEvent.click(saveDatasetMenuItem);
+
+    const saveDatasetHeader = screen.getByText(/save or overwrite dataset/i);
+
+    expect(saveDatasetHeader).toBeVisible();
+  });
+
+  it('renders the save dataset modal UI', () => {
+    render(<SaveQuery {...splitSaveBtnProps} />, { useRedux: true });
+
+    const caretBtn = screen.getByRole('button', { name: /caret-down/i });
+    userEvent.click(caretBtn);
+
+    const saveDatasetMenuItem = screen.getByText(/save dataset/i);
+    userEvent.click(saveDatasetMenuItem);
+
+    const closeBtn = screen.getByRole('button', { name: /close/i });
+    const saveDatasetHeader = screen.getByText(/save or overwrite dataset/i);
+    const saveRadio = screen.getByRole('radio', {
+      name: /save as new undefined/i,
+    });
+    const saveLabel = screen.getByText(/save as new/i);
+    const saveTextbox = screen.getByRole('textbox');
+    const overwriteRadio = screen.getByRole('radio', {
+      name: /overwrite existing select or type dataset name/i,
+    });
+    const overwriteLabel = screen.getByText(/overwrite existing/i);
+    const overwriteCombobox = screen.getByRole('combobox');
+    const overwritePlaceholderText = screen.getByText(
+      /select or type dataset name/i,
+    );
 
-    expect(modal.find(Button)).toHaveLength(3);
-    modal.find(Button).at(0).simulate('click');
-    expect(updateSpy.calledOnce).toBe(true);
+    expect(saveDatasetHeader).toBeVisible();
+    expect(closeBtn).toBeVisible();
+    expect(saveRadio).toBeVisible();
+    expect(saveLabel).toBeVisible();
+    expect(saveTextbox).toBeVisible();
+    expect(overwriteRadio).toBeVisible();
+    expect(overwriteLabel).toBeVisible();
+    expect(overwriteCombobox).toBeVisible();
+    expect(overwritePlaceholderText).toBeVisible();
   });
 });
diff --git a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx 
b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
index 467eb6a185..aa0c10de4c 100644
--- a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
@@ -19,7 +19,7 @@
 import React, { useState, useEffect } from 'react';
 import { Row, Col } from 'src/components';
 import { Input, TextArea } from 'src/components/Input';
-import { t, styled, useTheme } from '@superset-ui/core';
+import { t, styled } from '@superset-ui/core';
 import Button from 'src/components/Button';
 import { Menu } from 'src/components/Menu';
 import { Form, FormItem } from 'src/components/Form';
@@ -62,6 +62,18 @@ type QueryPayload = {
   title: string;
 };
 
+const Styles = styled.span`
+  span[role='img'] {
+    display: flex;
+    margin: 0;
+    color: ${({ theme }) => theme.colors.grayscale.base};
+    svg {
+      vertical-align: -${({ theme }) => theme.gridUnit * 1.25}px;
+      margin: 0;
+    }
+  }
+`;
+
 export default function SaveQuery({
   query,
   defaultLabel = t('Undefined'),
@@ -77,21 +89,8 @@ export default function SaveQuery({
   const [showSave, setShowSave] = useState<boolean>(false);
   const [showSaveDatasetModal, setShowSaveDatasetModal] = useState(false);
   const isSaved = !!query.remoteId;
-  const theme = useTheme();
   const canExploreDatabase = !!database?.allows_virtual_table_explore;
 
-  const Styles = styled.span`
-    span[role='img'] {
-      display: flex;
-      margin: 0;
-      color: ${theme.colors.grayscale.base};
-      svg {
-        vertical-align: -${theme.gridUnit * 1.25}px;
-        margin: 0;
-      }
-    }
-  `;
-
   const overlayMenu = (
     <Menu>
       <Menu.Item onClick={() => setShowSaveDatasetModal(true)}>
@@ -107,14 +106,10 @@ export default function SaveQuery({
   });
 
   useEffect(() => {
-    if (!isSaved) {
-      setLabel(defaultLabel);
-    }
+    if (!isSaved) setLabel(defaultLabel);
   }, [defaultLabel]);
 
-  const close = () => {
-    setShowSave(false);
-  };
+  const close = () => setShowSave(false);
 
   const onSaveWrapper = () => {
     onSave(queryPayload());
@@ -134,9 +129,7 @@ export default function SaveQuery({
     setDescription(e.target.value);
   };
 
-  const toggleSave = () => {
-    setShowSave(!showSave);
-  };
+  const toggleSave = () => setShowSave(!showSave);
 
   const renderModalBody = () => (
     <Form layout="vertical">

Reply via email to