mirror of
https://github.com/apache/superset.git
synced 2024-09-06 22:07:34 -04:00
test: Adds tests to URLShortLinkButton component (#13319)
This commit is contained in:
parent
8395b3d6c8
commit
72721845e1
55
superset-frontend/spec/helpers/reducerIndex.ts
Normal file
55
superset-frontend/spec/helpers/reducerIndex.ts
Normal file
@ -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,
|
||||||
|
};
|
@ -20,15 +20,41 @@ import '@testing-library/jest-dom/extend-expect';
|
|||||||
import React, { ReactNode, ReactElement } from 'react';
|
import React, { ReactNode, ReactElement } from 'react';
|
||||||
import { render, RenderOptions } from '@testing-library/react';
|
import { render, RenderOptions } from '@testing-library/react';
|
||||||
import { ThemeProvider, supersetTheme } from '@superset-ui/core';
|
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 }) {
|
type Options = Omit<RenderOptions, 'queries'> & {
|
||||||
return <ThemeProvider theme={supersetTheme}>{children}</ThemeProvider>;
|
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 }) => (
|
||||||
|
<Provider store={store}>
|
||||||
|
<ThemeProvider theme={supersetTheme}>{children}</ThemeProvider>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ({ children }: { children?: ReactNode }) => (
|
||||||
|
<ThemeProvider theme={supersetTheme}>{children}</ThemeProvider>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const customRender = (
|
const customRender = (ui: ReactElement, options?: Options) =>
|
||||||
ui: ReactElement,
|
render(ui, { wrapper: createWrapper(options), ...options });
|
||||||
options?: Omit<RenderOptions, 'queries'>,
|
|
||||||
) => render(ui, { wrapper: SupersetProviders, ...options });
|
|
||||||
|
|
||||||
export function sleep(time: number) {
|
export function sleep(time: number) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
@ -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(
|
|
||||||
<URLShortLinkButton store={store} {...defaultProps} />,
|
|
||||||
).dive();
|
|
||||||
}
|
|
||||||
|
|
||||||
it('renders OverlayTrigger', () => {
|
|
||||||
const wrapper = setup();
|
|
||||||
expect(wrapper.find(Popover)).toExist();
|
|
||||||
});
|
|
||||||
});
|
|
@ -134,7 +134,7 @@ describe('Tabs', () => {
|
|||||||
const wrapper = setup({ editMode: true, onChangeTab });
|
const wrapper = setup({ editMode: true, onChangeTab });
|
||||||
wrapper
|
wrapper
|
||||||
.find(
|
.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
|
.at(1) // will not call if it is already selected
|
||||||
.simulate('click');
|
.simulate('click');
|
||||||
|
@ -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(<URLShortLinkButton />, { useRedux: true });
|
||||||
|
expect(screen.getByRole('button')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('renders overlay on click', async () => {
|
||||||
|
render(<URLShortLinkButton />, { useRedux: true });
|
||||||
|
userEvent.click(screen.getByRole('button'));
|
||||||
|
expect(await screen.findByRole('tooltip')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('obtains short url', async () => {
|
||||||
|
render(<URLShortLinkButton />, { 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(<URLShortLinkButton emailSubject={subject} emailContent={content} />, {
|
||||||
|
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(
|
||||||
|
<>
|
||||||
|
<URLShortLinkButton />
|
||||||
|
<ToastPresenter />
|
||||||
|
</>,
|
||||||
|
{ useRedux: true },
|
||||||
|
);
|
||||||
|
userEvent.click(screen.getByRole('button'));
|
||||||
|
expect(await screen.findByRole('alert')).toBeInTheDocument();
|
||||||
|
});
|
@ -20,9 +20,9 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { t } from '@superset-ui/core';
|
import { t } from '@superset-ui/core';
|
||||||
import Popover from 'src/common/components/Popover';
|
import Popover from 'src/common/components/Popover';
|
||||||
import CopyToClipboard from './CopyToClipboard';
|
import CopyToClipboard from 'src/components/CopyToClipboard';
|
||||||
import { getShortUrl } from '../utils/urlUtils';
|
import { getShortUrl } from 'src/utils/urlUtils';
|
||||||
import withToasts from '../messageToasts/enhancers/withToasts';
|
import withToasts from 'src/messageToasts/enhancers/withToasts';
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
url: PropTypes.string,
|
url: PropTypes.string,
|
||||||
@ -85,7 +85,7 @@ class URLShortLinkButton extends React.Component {
|
|||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
className="short-link-trigger btn btn-default btn-sm"
|
className="short-link-trigger btn btn-default btn-sm"
|
||||||
data-test="short-link-button"
|
role="button"
|
||||||
>
|
>
|
||||||
<i className="short-link-trigger fa fa-link" />
|
<i className="short-link-trigger fa fa-link" />
|
||||||
|
|
@ -93,6 +93,7 @@ export default function Toast({ toast, onCloseToast }: ToastPresenterProps) {
|
|||||||
<ToastContainer
|
<ToastContainer
|
||||||
className={cx('alert', 'toast', visible && 'toast--visible', className)}
|
className={cx('alert', 'toast', visible && 'toast--visible', className)}
|
||||||
data-test="toast-container"
|
data-test="toast-container"
|
||||||
|
role="alert"
|
||||||
>
|
>
|
||||||
<StyledIcon name={iconName} />
|
<StyledIcon name={iconName} />
|
||||||
<Interweave content={toast.text} />
|
<Interweave content={toast.text} />
|
||||||
|
Loading…
Reference in New Issue
Block a user