From 493426a81a7736d114472262957bb47b842327d9 Mon Sep 17 00:00:00 2001 From: geido Date: Tue, 23 Feb 2021 20:16:25 +0200 Subject: [PATCH 1/4] Add tests for the Menu component --- .../spec/javascripts/components/Menu_spec.jsx | 212 ------------- .../src/components/Menu/LanguagePicker.tsx | 1 + .../src/components/Menu/Menu.test.tsx | 283 ++++++++++++++++++ 3 files changed, 284 insertions(+), 212 deletions(-) delete mode 100644 superset-frontend/spec/javascripts/components/Menu_spec.jsx create mode 100644 superset-frontend/src/components/Menu/Menu.test.tsx diff --git a/superset-frontend/spec/javascripts/components/Menu_spec.jsx b/superset-frontend/spec/javascripts/components/Menu_spec.jsx deleted file mode 100644 index 3b28388d11090..0000000000000 --- a/superset-frontend/spec/javascripts/components/Menu_spec.jsx +++ /dev/null @@ -1,212 +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 { styledMount as mount } from 'spec/helpers/theming'; -import { shallow } from 'enzyme'; -import { Nav } from 'react-bootstrap'; -import { Menu as DropdownMenu } from 'src/common/components'; -import NavDropdown from 'src/components/NavDropdown'; -import { Link } from 'react-router-dom'; - -import { Menu } from 'src/components/Menu/Menu'; -import MenuObject from 'src/components/Menu/MenuObject'; - -const defaultProps = { - data: { - menu: [ - { - name: 'Home', - icon: '', - label: 'Home', - url: '/superset/welcome', - }, - { - name: 'Sources', - icon: 'fa-table', - label: 'Sources', - childs: [ - { - name: 'Datasets', - icon: 'fa-table', - label: 'Datasets', - url: '/tablemodelview/list/', - }, - '-', - { - name: 'Databases', - icon: 'fa-database', - label: 'Databases', - url: '/databaseview/list/', - }, - ], - }, - { - name: 'Charts', - icon: 'fa-bar-chart', - label: 'Charts', - url: '/chart/list/', - }, - { - name: 'Dashboards', - icon: 'fa-dashboard', - label: 'Dashboards', - url: '/dashboard/list/', - }, - ], - brand: { - path: '/superset/profile/admin/', - icon: '/static/assets/images/superset-logo-horiz.png', - alt: 'Superset', - width: '126', - }, - navbar_right: { - bug_report_url: null, - documentation_url: null, - languages: { - en: { - flag: 'us', - name: 'English', - url: '/lang/en', - }, - it: { - flag: 'it', - name: 'Italian', - url: '/lang/it', - }, - }, - show_language_picker: true, - user_is_anonymous: false, - user_info_url: '/users/userinfo/', - user_logout_url: '/logout/', - user_login_url: '/login/', - locale: 'en', - }, - settings: [ - { - name: 'Security', - icon: 'fa-cogs', - label: 'Security', - childs: [ - { - name: 'List Users', - icon: 'fa-user', - label: 'List Users', - url: '/users/list/', - }, - ], - }, - ], - }, -}; - -describe('Menu', () => { - let wrapper; - - const getWrapper = (overrideProps = {}) => { - const props = { - ...defaultProps, - ...overrideProps, - }; - return shallow(); - }; - - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('renders the brand', () => { - expect(wrapper.find('.navbar-brand')).toExist(); - }); - - it('renders 2 navs', () => { - expect(wrapper.find(Nav)).toHaveLength(2); - }); - - it('renders 4 elements in main Menu Nav for every user', () => { - expect(wrapper.find(MenuObject)).toHaveLength(4); - }); - - it('renders a logged out view', () => { - const loggedOutWrapper = getWrapper({ - data: { - ...defaultProps.data, - navbar_right: { - ...defaultProps.data.navbar_right, - user_is_anonymous: true, - }, - }, - }); - expect(loggedOutWrapper.find('i.fa-sign-in')).toHaveLength(1); - expect(loggedOutWrapper.find('i.fa-user')).toHaveLength(0); - }); - - it('renders version number and SHA', () => { - const overrideProps = { - data: { - ...defaultProps.data, - navbar_right: { - ...defaultProps.data.navbar_right, - version_string: 'A1', - version_sha: 'X', - }, - }, - }; - - const props = { - ...defaultProps, - ...overrideProps, - }; - - const versionedWrapper = mount(); - - expect(versionedWrapper.find('.version-info span')).toHaveLength(2); - }); - - it('renders a NavDropdown (settings)', () => { - expect(wrapper.find(NavDropdown)).toHaveLength(1); - }); - - it('renders MenuItems in NavDropdown (settings)', () => { - expect(wrapper.find(NavDropdown).find(DropdownMenu.Item)).toHaveLength(3); - }); - - it('renders a react-router Link if isFrontendRoute', () => { - const props = { - ...defaultProps, - isFrontendRoute: jest.fn(() => true), - }; - - const wrapper2 = mount(); - - expect(props.isFrontendRoute).toHaveBeenCalled(); - expect(wrapper2.find(Link)).toExist(); - }); - - it('does not render a react-router Link if not isFrontendRoute', () => { - const props = { - ...defaultProps, - isFrontendRoute: jest.fn(() => false), - }; - - const wrapper2 = mount(); - - expect(props.isFrontendRoute).toHaveBeenCalled(); - expect(wrapper2.find(Link).exists()).toBe(false); - }); -}); diff --git a/superset-frontend/src/components/Menu/LanguagePicker.tsx b/superset-frontend/src/components/Menu/LanguagePicker.tsx index f125c0aee62c4..63f6e6bae1bf0 100644 --- a/superset-frontend/src/components/Menu/LanguagePicker.tsx +++ b/superset-frontend/src/components/Menu/LanguagePicker.tsx @@ -51,6 +51,7 @@ export default function LanguagePicker({ } + data-test="language-picker" > { diff --git a/superset-frontend/src/components/Menu/Menu.test.tsx b/superset-frontend/src/components/Menu/Menu.test.tsx new file mode 100644 index 0000000000000..d62420bd1e778 --- /dev/null +++ b/superset-frontend/src/components/Menu/Menu.test.tsx @@ -0,0 +1,283 @@ +/** + * 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, configure } from 'spec/helpers/testing-library'; +import { Menu } from './Menu'; + +configure({ testIdAttribute: 'data-test' }); + +const mockedProps = { + data: { + menu: [ + { + name: 'Home', + icon: '', + label: 'Home', + url: '/superset/welcome', + index: 1, + }, + { + name: 'Sources', + icon: 'fa-table', + label: 'Sources', + index: 2, + childs: [ + { + name: 'Datasets', + icon: 'fa-table', + label: 'Datasets', + url: '/tablemodelview/list/', + index: 1, + }, + '-', + { + name: 'Databases', + icon: 'fa-database', + label: 'Databases', + url: '/databaseview/list/', + index: 2, + }, + ], + }, + { + name: 'Charts', + icon: 'fa-bar-chart', + label: 'Charts', + url: '/chart/list/', + index: 3, + }, + { + name: 'Dashboards', + icon: 'fa-dashboard', + label: 'Dashboards', + url: '/dashboard/list/', + index: 4, + }, + ], + brand: { + path: '/superset/profile/admin/', + icon: '/static/assets/images/superset-logo-horiz.png', + alt: 'Superset', + width: '126', + }, + navbar_right: { + bug_report_url: '/report/', + documentation_url: '/docs/', + languages: { + en: { + flag: 'us', + name: 'English', + url: '/lang/en', + }, + it: { + flag: 'it', + name: 'Italian', + url: '/lang/it', + }, + }, + show_language_picker: true, + user_is_anonymous: true, + user_info_url: '/users/userinfo/', + user_logout_url: '/logout/', + user_login_url: '/login/', + user_profile_url: '/profile/', + locale: 'en', + version_string: '1.0.0', + version_sha: 'randomSHA', + }, + settings: [ + { + name: 'Security', + icon: 'fa-cogs', + label: 'Security', + index: 1, + childs: [ + { + name: 'List Users', + icon: 'fa-user', + label: 'List Users', + url: '/users/list/', + index: 1, + }, + ], + }, + ], + }, +}; + +const notanonProps = { + ...mockedProps, + data: { + ...mockedProps.data, + navbar_right: { + ...mockedProps.data.navbar_right, + user_is_anonymous: false, + }, + }, +}; + +test('should render', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); +}); + +test('should render the navigation', () => { + render(); + expect(screen.getByRole('navigation')).toBeInTheDocument(); +}); + +test('should render the brand', () => { + const { + data: { + brand: { alt, icon }, + }, + } = mockedProps; + render(); + const image = screen.getByAltText(alt); + expect(image).toHaveAttribute('src', icon); +}); + +test('should render all the top navbar menu items', () => { + const { + data: { menu }, + } = mockedProps; + render(); + menu.forEach(item => { + expect(screen.getByText(item.name)).toBeInTheDocument(); + }); +}); + +test('should render the top navbar child menu items', () => { + render(); + expect(screen.getByText('Datasets')).toBeInTheDocument(); + expect(screen.getByText('Databases')).toBeInTheDocument(); +}); + +test('should render the Settings', () => { + render(); + expect(screen.getByText('Settings')).toBeInTheDocument(); +}); + +test('should render the Settings menu', () => { + render(); + expect(screen.getByText('Security')).toBeInTheDocument(); +}); + +test('should render the Settings dropdown child menu items', () => { + render(); + expect(screen.getByText('List Users')).toBeInTheDocument(); +}); + +test('should render the plus menu (+) when user is not anonymous', () => { + render(); + expect(screen.getByTestId('new-dropdown')).toBeInTheDocument(); +}); + +test('should NOT render the plus menu (+) when user is anonymous', () => { + render(); + expect(screen.queryByTestId('new-dropdown')).not.toBeInTheDocument(); +}); + +test('should render the user actions when user is not anonymous', () => { + const { + data: { + navbar_right: { user_info_url, user_logout_url }, + }, + } = mockedProps; + + render(); + expect(screen.getByText('User')).toBeInTheDocument(); + + const infoLinK = screen.getByText('Info'); + const logoutLink = screen.getByText('Logout'); + + expect(infoLinK).toHaveAttribute('href', user_info_url); + expect(logoutLink).toHaveAttribute('href', user_logout_url); +}); + +test('should NOT render the user actions when user is anonymous', () => { + render(); + expect(screen.queryByText('User')).not.toBeInTheDocument(); +}); + +test('should render the Profile link when available', () => { + const { + data: { + navbar_right: { user_profile_url }, + }, + } = mockedProps; + + render(); + const profileLink = screen.getByText('Profile'); + expect(profileLink).toHaveAttribute('href', user_profile_url); +}); + +test('should render the About section and version_string or sha when available', () => { + const { + data: { + navbar_right: { version_sha, version_string }, + }, + } = mockedProps; + + render(); + expect(screen.getByText('About')).toBeInTheDocument(); + expect(screen.getByText(`Version: ${version_string}`)).toBeInTheDocument(); + expect(screen.getByText(`SHA: ${version_sha}`)).toBeInTheDocument(); +}); + +test('should render the Documentation link when available', () => { + const { + data: { + navbar_right: { documentation_url }, + }, + } = mockedProps; + + render(); + const docLink = screen.getByTitle('Documentation'); + expect(docLink).toHaveAttribute('href', documentation_url); +}); + +test('should render the Bug Report link when available', () => { + const { + data: { + navbar_right: { bug_report_url }, + }, + } = mockedProps; + + render(); + const bugreportLink = screen.getByTitle('Report a Bug'); + expect(bugreportLink).toHaveAttribute('href', bug_report_url); +}); + +test('should render the Login link when user is anonymous', () => { + const { + data: { + navbar_right: { user_login_url }, + }, + } = mockedProps; + + render(); + const loginLink = screen.getByText('Login'); + expect(loginLink).toHaveAttribute('href', user_login_url); +}); + +test('should render the Language Picker', () => { + render(); + expect(screen.getByTestId('language-picker')).toBeInTheDocument(); +}); From 445f9d980e9d0619fee70183b80d915141689b67 Mon Sep 17 00:00:00 2001 From: geido Date: Wed, 24 Feb 2021 19:04:29 +0200 Subject: [PATCH 2/4] Clean up and add NewMenu - SubMenu tests --- .../src/components/Menu/Menu.test.tsx | 54 ++++++---- .../src/components/Menu/NewMenu.test.tsx | 34 ++++++ .../src/components/Menu/SubMenu.test.tsx | 100 ++++++++++++++++++ .../src/components/Menu/SubMenu.tsx | 2 + 4 files changed, 169 insertions(+), 21 deletions(-) create mode 100644 superset-frontend/src/components/Menu/NewMenu.test.tsx create mode 100644 superset-frontend/src/components/Menu/SubMenu.test.tsx diff --git a/superset-frontend/src/components/Menu/Menu.test.tsx b/superset-frontend/src/components/Menu/Menu.test.tsx index d62420bd1e778..b3a2273eb1bcb 100644 --- a/superset-frontend/src/components/Menu/Menu.test.tsx +++ b/superset-frontend/src/components/Menu/Menu.test.tsx @@ -17,11 +17,9 @@ * under the License. */ import React from 'react'; -import { render, screen, configure } from 'spec/helpers/testing-library'; +import { render, screen } from 'spec/helpers/testing-library'; import { Menu } from './Menu'; -configure({ testIdAttribute: 'data-test' }); - const mockedProps = { data: { menu: [ @@ -159,29 +157,43 @@ test('should render all the top navbar menu items', () => { } = mockedProps; render(); menu.forEach(item => { - expect(screen.getByText(item.name)).toBeInTheDocument(); + const menuItem = screen.getByText(item.label); + expect(menuItem).toHaveAttribute('href', item.url); }); }); test('should render the top navbar child menu items', () => { + const { + data: { menu }, + } = mockedProps; render(); - expect(screen.getByText('Datasets')).toBeInTheDocument(); - expect(screen.getByText('Databases')).toBeInTheDocument(); + const datasets = screen.getByText('Datasets'); + const databases = screen.getByText('Databases'); + const dataset = menu[1].childs![0] as { url: string }; + const database = menu[1].childs![2] as { url: string }; + + expect(datasets).toHaveAttribute('href', dataset.url); + expect(databases).toHaveAttribute('href', database.url); }); test('should render the Settings', () => { render(); - expect(screen.getByText('Settings')).toBeInTheDocument(); + const settings = screen.getByText('Settings'); + expect(settings).toHaveAttribute('href', '#'); }); -test('should render the Settings menu', () => { +test('should render the Settings menu item', () => { render(); expect(screen.getByText('Security')).toBeInTheDocument(); }); test('should render the Settings dropdown child menu items', () => { + const { + data: { settings }, + } = mockedProps; render(); - expect(screen.getByText('List Users')).toBeInTheDocument(); + const listUsers = screen.getByText('List Users'); + expect(listUsers).toHaveAttribute('href', settings[0].childs[0].url); }); test('should render the plus menu (+) when user is not anonymous', () => { @@ -204,11 +216,11 @@ test('should render the user actions when user is not anonymous', () => { render(); expect(screen.getByText('User')).toBeInTheDocument(); - const infoLinK = screen.getByText('Info'); - const logoutLink = screen.getByText('Logout'); + const info = screen.getByText('Info'); + const logout = screen.getByText('Logout'); - expect(infoLinK).toHaveAttribute('href', user_info_url); - expect(logoutLink).toHaveAttribute('href', user_logout_url); + expect(info).toHaveAttribute('href', user_info_url); + expect(logout).toHaveAttribute('href', user_logout_url); }); test('should NOT render the user actions when user is anonymous', () => { @@ -224,8 +236,8 @@ test('should render the Profile link when available', () => { } = mockedProps; render(); - const profileLink = screen.getByText('Profile'); - expect(profileLink).toHaveAttribute('href', user_profile_url); + const profile = screen.getByText('Profile'); + expect(profile).toHaveAttribute('href', user_profile_url); }); test('should render the About section and version_string or sha when available', () => { @@ -249,8 +261,8 @@ test('should render the Documentation link when available', () => { } = mockedProps; render(); - const docLink = screen.getByTitle('Documentation'); - expect(docLink).toHaveAttribute('href', documentation_url); + const doc = screen.getByTitle('Documentation'); + expect(doc).toHaveAttribute('href', documentation_url); }); test('should render the Bug Report link when available', () => { @@ -261,8 +273,8 @@ test('should render the Bug Report link when available', () => { } = mockedProps; render(); - const bugreportLink = screen.getByTitle('Report a Bug'); - expect(bugreportLink).toHaveAttribute('href', bug_report_url); + const bugReport = screen.getByTitle('Report a Bug'); + expect(bugReport).toHaveAttribute('href', bug_report_url); }); test('should render the Login link when user is anonymous', () => { @@ -273,8 +285,8 @@ test('should render the Login link when user is anonymous', () => { } = mockedProps; render(); - const loginLink = screen.getByText('Login'); - expect(loginLink).toHaveAttribute('href', user_login_url); + const login = screen.getByText('Login'); + expect(login).toHaveAttribute('href', user_login_url); }); test('should render the Language Picker', () => { diff --git a/superset-frontend/src/components/Menu/NewMenu.test.tsx b/superset-frontend/src/components/Menu/NewMenu.test.tsx new file mode 100644 index 0000000000000..b325370cec39e --- /dev/null +++ b/superset-frontend/src/components/Menu/NewMenu.test.tsx @@ -0,0 +1,34 @@ +/** + * 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 NewMenu, { dropdownItems } from './NewMenu'; + +test('should render', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); +}); + +test('should render the dropdown items', () => { + render(); + dropdownItems.forEach(item => { + expect(screen.getByText(item.label)).toHaveAttribute('href', item.url); + expect(screen.getByTestId(`menu-item-${item.label}`)).toBeInTheDocument(); + }); +}); diff --git a/superset-frontend/src/components/Menu/SubMenu.test.tsx b/superset-frontend/src/components/Menu/SubMenu.test.tsx new file mode 100644 index 0000000000000..a7c2a557f38af --- /dev/null +++ b/superset-frontend/src/components/Menu/SubMenu.test.tsx @@ -0,0 +1,100 @@ +/** + * 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 userEvent from '@testing-library/user-event'; +import React from 'react'; +import { render, screen } from 'spec/helpers/testing-library'; +import SubMenu, { ButtonProps } from './SubMenu'; + +const mockedProps = { + name: 'Title', + tabs: [ + { + name: 'Page1', + label: 'Page1', + url: '/page1', + usesRouter: true, + }, + { + name: 'Page2', + label: 'Page2', + url: '/page2', + usesRouter: true, + }, + { + name: 'Page3', + label: 'Page3', + url: '/page3', + usesRouter: false, + }, + ], +}; + +test('should render', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); +}); + +test('should render the navigation', () => { + render(); + expect(screen.getByRole('navigation')).toBeInTheDocument(); +}); + +test('should render the brand', () => { + render(); + expect(screen.getByText('Title')).toBeInTheDocument(); +}); + +test('should render the right number of tabs', () => { + render(); + expect(screen.getAllByRole('tab')).toHaveLength(3); +}); + +test('should render all the tabs links', () => { + const { tabs } = mockedProps; + render(); + tabs.forEach(tab => { + const tabItem = screen.getByText(tab.label); + expect(tabItem).toHaveAttribute('href', tab.url); + }); +}); + +test('should render the buttons', () => { + const mockFunc = jest.fn(); + const buttons = [ + { + name: 'test_button', + onClick: mockFunc, + buttonStyle: 'primary' as ButtonProps['buttonStyle'], + }, + { + name: 'danger_button', + onClick: mockFunc, + buttonStyle: 'danger' as ButtonProps['buttonStyle'], + }, + ]; + const buttonsProps = { + ...mockedProps, + buttons, + }; + render(); + const testButton = screen.getByText(buttons[0].name); + expect(screen.getAllByRole('button')).toHaveLength(2); + userEvent.click(testButton); + expect(mockFunc).toHaveBeenCalled(); +}); diff --git a/superset-frontend/src/components/Menu/SubMenu.tsx b/superset-frontend/src/components/Menu/SubMenu.tsx index 0efd3cdf5f87f..d109aa7f4c507 100644 --- a/superset-frontend/src/components/Menu/SubMenu.tsx +++ b/superset-frontend/src/components/Menu/SubMenu.tsx @@ -141,6 +141,7 @@ const SubMenu: React.FunctionComponent = props => { return (
  • @@ -158,6 +159,7 @@ const SubMenu: React.FunctionComponent = props => { className={cx('no-router', { active: tab.name === props.activeChild, })} + role="tab" > {tab.label} From e3ef780666f86a37ad45aede643359bc7b8895d9 Mon Sep 17 00:00:00 2001 From: geido Date: Wed, 24 Feb 2021 19:10:24 +0200 Subject: [PATCH 3/4] Remove obsolete SubMenu test --- .../javascripts/components/SubMenu_spec.jsx | 108 ------------------ 1 file changed, 108 deletions(-) delete mode 100644 superset-frontend/spec/javascripts/components/SubMenu_spec.jsx diff --git a/superset-frontend/spec/javascripts/components/SubMenu_spec.jsx b/superset-frontend/spec/javascripts/components/SubMenu_spec.jsx deleted file mode 100644 index 46259328f8401..0000000000000 --- a/superset-frontend/spec/javascripts/components/SubMenu_spec.jsx +++ /dev/null @@ -1,108 +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 { Link } from 'react-router-dom'; -import { shallow } from 'enzyme'; -import { Navbar } from 'react-bootstrap'; -import SubMenu from 'src/components/Menu/SubMenu'; - -const defaultProps = { - name: 'Title', - tabs: [ - { - name: 'Page1', - label: 'Page1', - url: '/page1', - usesRouter: true, - }, - { - name: 'Page2', - label: 'Page2', - url: '/page2', - usesRouter: true, - }, - { - name: 'Page3', - label: 'Page3', - url: '/page3', - usesRouter: false, - }, - ], -}; - -describe('SubMenu', () => { - let wrapper; - - const getWrapper = (overrideProps = {}) => { - const props = { - ...defaultProps, - ...overrideProps, - }; - return shallow(); - }; - - beforeEach(() => { - wrapper = getWrapper(); - }); - - it('renders a Navbar', () => { - expect(wrapper.find(Navbar)).toExist(); - }); - - it('renders 3 MenuItems (when usesRouter === false)', () => { - expect(wrapper.find('li')).toHaveLength(3); - }); - - it('renders the menu title', () => { - expect(wrapper.find(Navbar.Brand)).toExist(); - expect(wrapper.find(Navbar.Brand).children().text()).toEqual('Title'); - }); - - it('renders Link components when usesRouter === true', () => { - const overrideProps = { - usesRouter: true, - }; - - const routerWrapper = getWrapper(overrideProps); - - expect(routerWrapper.find(Link)).toExist(); - expect(routerWrapper.find(Link)).toHaveLength(2); - expect(routerWrapper.find('li.no-router')).toHaveLength(1); - }); - - it('renders buttons in the right nav of the submenu', () => { - const mockFunc = jest.fn(); - const buttons = [ - { - name: 'test_button', - onClick: mockFunc, - buttonStyle: 'primary', - }, - { - name: 'danger_button', - buttonStyle: 'danger', - }, - ]; - const overrideProps = { buttons }; - const newWrapper = getWrapper(overrideProps); - expect(newWrapper.find('.navbar-right').children()).toHaveLength(2); - newWrapper.find('[buttonStyle="primary"]').simulate('click'); - expect(mockFunc).toHaveBeenCalled(); - }); -}); From 68c6bd05a591557ebe86f87585b742d370609cd4 Mon Sep 17 00:00:00 2001 From: geido Date: Wed, 24 Feb 2021 19:36:01 +0200 Subject: [PATCH 4/4] Add LanguagePicker tests --- .../components/Menu/LanguagePicker.test.tsx | 54 +++++++++++++++++++ .../src/components/Menu/NewMenu.tsx | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 superset-frontend/src/components/Menu/LanguagePicker.test.tsx diff --git a/superset-frontend/src/components/Menu/LanguagePicker.test.tsx b/superset-frontend/src/components/Menu/LanguagePicker.test.tsx new file mode 100644 index 0000000000000..ad494d620ca81 --- /dev/null +++ b/superset-frontend/src/components/Menu/LanguagePicker.test.tsx @@ -0,0 +1,54 @@ +/** + * 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 LanguagePicker from './LanguagePicker'; + +const mockedProps = { + locale: 'en', + languages: { + en: { + flag: 'us', + name: 'English', + url: '/lang/en', + }, + it: { + flag: 'it', + name: 'Italian', + url: '/lang/it', + }, + }, +}; + +test('should render', () => { + const { container } = render(); + expect(container).toBeInTheDocument(); +}); + +test('should render the button', () => { + render(); + const button = screen.getByRole('button'); + expect(button).toHaveAttribute('href', '#'); +}); + +test('should render the menuitem', () => { + render(); + const menuitem = screen.getByRole('menuitem'); + expect(menuitem).toHaveTextContent('Italian'); +}); diff --git a/superset-frontend/src/components/Menu/NewMenu.tsx b/superset-frontend/src/components/Menu/NewMenu.tsx index b2aa9b2ad7d2b..8ff46d29538f9 100644 --- a/superset-frontend/src/components/Menu/NewMenu.tsx +++ b/superset-frontend/src/components/Menu/NewMenu.tsx @@ -21,7 +21,7 @@ import { t, styled } from '@superset-ui/core'; import { Menu } from 'src/common/components'; import NavDropdown from 'src/components/NavDropdown'; -const dropdownItems = [ +export const dropdownItems = [ { label: t('SQL query'), url: '/superset/sqllab',