diff --git a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx index 86730fedeb..e96291c9b6 100644 --- a/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx +++ b/superset-frontend/src/dashboard/components/CssEditor/CssEditor.test.tsx @@ -17,7 +17,7 @@ * under the License. */ import React from 'react'; -import { render, screen } from 'spec/helpers/testing-library'; +import { render, screen, waitFor } from 'spec/helpers/testing-library'; import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor'; import { AceEditorProps } from 'react-ace'; import userEvent from '@testing-library/user-event'; @@ -32,6 +32,12 @@ jest.mock('src/components/AsyncAceEditor', () => ({ ), })); +const templates = [ + { label: 'Template A', css: 'background-color: red;' }, + { label: 'Template B', css: 'background-color: blue;' }, + { label: 'Template C', css: 'background-color: yellow;' }, +]; + AceCssEditor.preload = () => new Promise(() => {}); test('renders with default props', () => { @@ -46,14 +52,15 @@ test('renders with initial CSS', () => { expect(screen.getByText(initialCss)).toBeInTheDocument(); }); -test('renders with templates', () => { - const templates = ['Template A', 'Template B', 'Template C']; +test('renders with templates', async () => { render(Click} templates={templates} />); userEvent.click(screen.getByRole('button', { name: 'Click' })); - userEvent.click(screen.getByText('Load a CSS template')); - templates.forEach(template => - expect(screen.getByText(template)).toBeInTheDocument(), - ); + userEvent.hover(screen.getByText('Load a CSS template')); + await waitFor(() => { + templates.forEach(template => + expect(screen.getByText(template.label)).toBeInTheDocument(), + ); + }); }); test('triggers onChange when using the editor', () => { @@ -73,9 +80,8 @@ test('triggers onChange when using the editor', () => { expect(onChange).toHaveBeenLastCalledWith(initialCss.concat(additionalCss)); }); -test('triggers onChange when selecting a template', () => { +test('triggers onChange when selecting a template', async () => { const onChange = jest.fn(); - const templates = ['Template A', 'Template B', 'Template C']; render( Click} @@ -86,6 +92,6 @@ test('triggers onChange when selecting a template', () => { userEvent.click(screen.getByRole('button', { name: 'Click' })); userEvent.click(screen.getByText('Load a CSS template')); expect(onChange).not.toHaveBeenCalled(); - userEvent.click(screen.getByText('Template A')); + userEvent.click(await screen.findByText('Template A')); expect(onChange).toHaveBeenCalledTimes(1); }); diff --git a/superset-frontend/src/dashboard/components/CssEditor/index.jsx b/superset-frontend/src/dashboard/components/CssEditor/index.jsx index da0b432044..995dc081fe 100644 --- a/superset-frontend/src/dashboard/components/CssEditor/index.jsx +++ b/superset-frontend/src/dashboard/components/CssEditor/index.jsx @@ -18,11 +18,30 @@ */ import React from 'react'; import PropTypes from 'prop-types'; -import Select from 'src/components/Select'; -import { t } from '@superset-ui/core'; +import { Menu, Dropdown } from 'src/common/components'; +import Button from 'src/components/Button'; +import { t, styled } from '@superset-ui/core'; import ModalTrigger from 'src/components/ModalTrigger'; import { CssEditor as AceCssEditor } from 'src/components/AsyncAceEditor'; +const StyledWrapper = styled.div` + ${({ theme }) => ` + .css-editor-header { + display: flex; + flex-direction: row; + justify-content: space-between; + margin-bottom: ${theme.gridUnit * 2}px; + + h5 { + margin-top: ${theme.gridUnit}px; + } + } + .css-editor { + border: 1px solid ${theme.colors.grayscale.light1}; + } + `} +`; + const propTypes = { initialCss: PropTypes.string, triggerNode: PropTypes.node.isRequired, @@ -55,21 +74,24 @@ class CssEditor extends React.PureComponent { }); } - changeCssTemplate(opt) { - this.changeCss(opt.css); + changeCssTemplate({ key }) { + this.changeCss(key); } renderTemplateSelector() { if (this.props.templates) { + const menu = ( + + {this.props.templates.map(template => ( + {template.label} + ))} + + ); + return ( -
-
{t('Load a template')}
-