From 72721845e1e0c23956df51fd849539a61cb3e4ca Mon Sep 17 00:00:00 2001 From: "Michael S. Molina" <70410625+michael-s-molina@users.noreply.github.com> Date: Thu, 25 Feb 2021 15:59:36 -0300 Subject: [PATCH] test: Adds tests to URLShortLinkButton component (#13319) --- .../spec/helpers/reducerIndex.ts | 55 ++++++++++++++ .../spec/helpers/testing-library.tsx | 38 ++++++++-- .../components/URLShortLinkButton_spec.jsx | 45 ----------- .../components/gridComponents/Tabs_spec.jsx | 2 +- .../URLShortLinkButton.test.tsx | 74 +++++++++++++++++++ .../index.jsx} | 8 +- .../src/messageToasts/components/Toast.tsx | 1 + 7 files changed, 167 insertions(+), 56 deletions(-) create mode 100644 superset-frontend/spec/helpers/reducerIndex.ts delete mode 100644 superset-frontend/spec/javascripts/components/URLShortLinkButton_spec.jsx create mode 100644 superset-frontend/src/components/URLShortLinkButton/URLShortLinkButton.test.tsx rename superset-frontend/src/components/{URLShortLinkButton.jsx => URLShortLinkButton/index.jsx} (93%) diff --git a/superset-frontend/spec/helpers/reducerIndex.ts b/superset-frontend/spec/helpers/reducerIndex.ts new file mode 100644 index 0000000000..41b5aff1b2 --- /dev/null +++ b/superset-frontend/spec/helpers/reducerIndex.ts @@ -0,0 +1,55 @@ +/** + * 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 charts from 'src/chart/chartReducer'; +import dashboardInfo from 'src/dashboard/reducers/dashboardInfo'; +import dashboardState from 'src/dashboard/reducers/dashboardState'; +import dashboardFilters from 'src/dashboard/reducers/dashboardFilters'; +import nativeFilters from 'src/dashboard/reducers/nativeFilters'; +import datasources from 'src/dashboard/reducers/datasources'; +import sliceEntities from 'src/dashboard/reducers/sliceEntities'; +import dashboardLayout from 'src/dashboard/reducers/undoableDashboardLayout'; +import messageToasts from 'src/messageToasts/reducers'; +import saveModal from 'src/explore/reducers/saveModalReducer'; +import explore from 'src/explore/reducers/exploreReducer'; +import sqlLab from 'src/SqlLab/reducers/sqlLab'; +import localStorageUsageInKilobytes from 'src/SqlLab/reducers/localStorageUsage'; + +const impressionId = (state = '') => state; + +const container = document.getElementById('app'); +const bootstrap = JSON.parse(container?.getAttribute('data-bootstrap') ?? '{}'); +const common = { ...bootstrap.common }; + +export default { + charts, + datasources, + dashboardInfo, + dashboardFilters, + nativeFilters, + dashboardState, + dashboardLayout, + impressionId, + messageToasts, + sliceEntities, + saveModal, + explore, + sqlLab, + localStorageUsageInKilobytes, + common, +}; diff --git a/superset-frontend/spec/helpers/testing-library.tsx b/superset-frontend/spec/helpers/testing-library.tsx index 2727679352..71672444dd 100644 --- a/superset-frontend/spec/helpers/testing-library.tsx +++ b/superset-frontend/spec/helpers/testing-library.tsx @@ -20,15 +20,41 @@ import '@testing-library/jest-dom/extend-expect'; import React, { ReactNode, ReactElement } from 'react'; import { render, RenderOptions } from '@testing-library/react'; import { ThemeProvider, supersetTheme } from '@superset-ui/core'; +import { Provider } from 'react-redux'; +import { combineReducers, createStore, applyMiddleware, compose } from 'redux'; +import thunk from 'redux-thunk'; +import reducerIndex from 'spec/helpers/reducerIndex'; -function SupersetProviders({ children }: { children?: ReactNode }) { - return {children}; +type Options = Omit & { + useRedux?: boolean; + initialState?: {}; + reducers?: {}; +}; + +function createWrapper(options?: Options) { + const { useRedux, initialState, reducers } = options || {}; + + if (useRedux) { + const store = createStore( + combineReducers(reducers || reducerIndex), + initialState || {}, + compose(applyMiddleware(thunk)), + ); + + return ({ children }: { children?: ReactNode }) => ( + + {children} + + ); + } + + return ({ children }: { children?: ReactNode }) => ( + {children} + ); } -const customRender = ( - ui: ReactElement, - options?: Omit, -) => render(ui, { wrapper: SupersetProviders, ...options }); +const customRender = (ui: ReactElement, options?: Options) => + render(ui, { wrapper: createWrapper(options), ...options }); export function sleep(time: number) { return new Promise(resolve => { diff --git a/superset-frontend/spec/javascripts/components/URLShortLinkButton_spec.jsx b/superset-frontend/spec/javascripts/components/URLShortLinkButton_spec.jsx deleted file mode 100644 index fc6194248c..0000000000 --- a/superset-frontend/spec/javascripts/components/URLShortLinkButton_spec.jsx +++ /dev/null @@ -1,45 +0,0 @@ -/** - * 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 configureStore from 'redux-mock-store'; -import { shallow } from 'enzyme'; - -import Popover from 'src/common/components/Popover'; -import URLShortLinkButton from 'src/components/URLShortLinkButton'; - -describe('URLShortLinkButton', () => { - const defaultProps = { - url: 'mockURL', - emailSubject: 'Mock Subject', - emailContent: 'mock content', - }; - - function setup() { - const mockStore = configureStore([]); - const store = mockStore({}); - return shallow( - , - ).dive(); - } - - it('renders OverlayTrigger', () => { - const wrapper = setup(); - expect(wrapper.find(Popover)).toExist(); - }); -}); diff --git a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx index b9e38c6ad2..78d5d637d8 100644 --- a/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx +++ b/superset-frontend/spec/javascripts/dashboard/components/gridComponents/Tabs_spec.jsx @@ -134,7 +134,7 @@ describe('Tabs', () => { const wrapper = setup({ editMode: true, onChangeTab }); wrapper .find( - '[data-test="dashboard-component-tabs"] .ant-tabs-tab [data-test="short-link-button"]', + '[data-test="dashboard-component-tabs"] .ant-tabs-tab [role="button"]', ) .at(1) // will not call if it is already selected .simulate('click'); diff --git a/superset-frontend/src/components/URLShortLinkButton/URLShortLinkButton.test.tsx b/superset-frontend/src/components/URLShortLinkButton/URLShortLinkButton.test.tsx new file mode 100644 index 0000000000..6bba1dee41 --- /dev/null +++ b/superset-frontend/src/components/URLShortLinkButton/URLShortLinkButton.test.tsx @@ -0,0 +1,74 @@ +/** + * 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 fetchMock from 'fetch-mock'; +import URLShortLinkButton from 'src/components/URLShortLinkButton'; +import ToastPresenter from 'src/messageToasts/containers/ToastPresenter'; + +const fakeUrl = 'http://fakeurl.com'; + +fetchMock.post('glob:*/r/shortner/', fakeUrl); + +test('renders with default props', () => { + render(, { useRedux: true }); + expect(screen.getByRole('button')).toBeInTheDocument(); +}); + +test('renders overlay on click', async () => { + render(, { useRedux: true }); + userEvent.click(screen.getByRole('button')); + expect(await screen.findByRole('tooltip')).toBeInTheDocument(); +}); + +test('obtains short url', async () => { + render(, { useRedux: true }); + userEvent.click(screen.getByRole('button')); + expect(await screen.findByRole('tooltip')).toHaveTextContent(fakeUrl); +}); + +test('creates email anchor', async () => { + const subject = 'Subject'; + const content = 'Content'; + + render(, { + useRedux: true, + }); + + const href = `mailto:?Subject=${subject}%20&Body=${content}${fakeUrl}`; + userEvent.click(screen.getByRole('button')); + expect(await screen.findByRole('link')).toHaveAttribute('href', href); +}); + +test('renders error message on short url error', async () => { + fetchMock.mock('glob:*/r/shortner/', 500, { + overwriteRoutes: true, + }); + + render( + <> + + + , + { useRedux: true }, + ); + userEvent.click(screen.getByRole('button')); + expect(await screen.findByRole('alert')).toBeInTheDocument(); +}); diff --git a/superset-frontend/src/components/URLShortLinkButton.jsx b/superset-frontend/src/components/URLShortLinkButton/index.jsx similarity index 93% rename from superset-frontend/src/components/URLShortLinkButton.jsx rename to superset-frontend/src/components/URLShortLinkButton/index.jsx index 68728f6abe..fb9fa89d1c 100644 --- a/superset-frontend/src/components/URLShortLinkButton.jsx +++ b/superset-frontend/src/components/URLShortLinkButton/index.jsx @@ -20,9 +20,9 @@ import React from 'react'; import PropTypes from 'prop-types'; import { t } from '@superset-ui/core'; import Popover from 'src/common/components/Popover'; -import CopyToClipboard from './CopyToClipboard'; -import { getShortUrl } from '../utils/urlUtils'; -import withToasts from '../messageToasts/enhancers/withToasts'; +import CopyToClipboard from 'src/components/CopyToClipboard'; +import { getShortUrl } from 'src/utils/urlUtils'; +import withToasts from 'src/messageToasts/enhancers/withToasts'; const propTypes = { url: PropTypes.string, @@ -85,7 +85,7 @@ class URLShortLinkButton extends React.Component { >   diff --git a/superset-frontend/src/messageToasts/components/Toast.tsx b/superset-frontend/src/messageToasts/components/Toast.tsx index a833b8ba0a..9018ed6ae2 100644 --- a/superset-frontend/src/messageToasts/components/Toast.tsx +++ b/superset-frontend/src/messageToasts/components/Toast.tsx @@ -93,6 +93,7 @@ export default function Toast({ toast, onCloseToast }: ToastPresenterProps) {