Skip to content

Commit

Permalink
feat: DBC-UI Globally available across the app 🌎 (#18722)
Browse files Browse the repository at this point in the history
* more data nav menu

* fix lint and fix nav css

* update test and remove icons

* Update superset-frontend/src/views/components/Menu.test.tsx

Co-authored-by: Hugh A. Miles II <hughmil3s@gmail.com>

* Apply suggestions from code review

* use backend app.link to show new nav changes

* fix lint

* update test

* usetheme and remove chaining

* add more suggestions

* fix lint

* working global db connection

* add allowed extensions to bootstrap and hard code links

* remove backend links

* fix test

* apply stashed gsheets

* fix check for google sheets

* setup gsheets

* add extensions to frontend conf

* fix test and add be changes

* remove package json changes

* test is python test passes

* update python test and reremove app links

* fix tslint issues

* fix other linting tools

* fix pylint

* fix test

* fix

* refactor

* fix lint

* working fixed test

* clean up test

* address concerns

* address concerns

* change to tenarary

Co-authored-by: Phillip Kelley-Dotson <pkelleydotson@yahoo.com>
  • Loading branch information
hughhhh and pkdotson authored Feb 24, 2022
1 parent 822dd6d commit 209e3f4
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 102 deletions.
99 changes: 78 additions & 21 deletions superset-frontend/src/views/components/Menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,64 @@ import * as reactRedux from 'react-redux';
import { render, screen } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import { Menu } from './Menu';
import { dropdownItems } from './MenuRight';

const dropdownItems = [
{
label: 'Data',
icon: 'fa-database',
childs: [
{
label: 'Connect Database',
name: 'dbconnect',
perm: true,
},
{
label: 'Connect Google Sheet',
name: 'gsheets',
perm: true,
},
{
label: 'Upload a CSV',
name: 'Upload a CSV',
url: '/csvtodatabaseview/form',
perm: true,
},
{
label: 'Upload a Columnar File',
name: 'Upload a Columnar file',
url: '/columnartodatabaseview/form',
perm: true,
},
{
label: 'Upload Excel',
name: 'Upload Excel',
url: '/exceltodatabaseview/form',
perm: true,
},
],
},
{
label: 'SQL query',
url: '/superset/sqllab?new=true',
icon: 'fa-fw fa-search',
perm: 'can_sqllab',
view: 'Superset',
},
{
label: 'Chart',
url: '/chart/add',
icon: 'fa-fw fa-bar-chart',
perm: 'can_write',
view: 'Chart',
},
{
label: 'Dashboard',
url: '/dashboard/new',
icon: 'fa-fw fa-dashboard',
perm: 'can_write',
view: 'Dashboard',
},
];

const user = {
createdOn: '2021-04-27T18:12:38.952304',
Expand Down Expand Up @@ -185,13 +242,13 @@ beforeEach(() => {

test('should render', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
const { container } = render(<Menu {...mockedProps} />);
const { container } = render(<Menu {...mockedProps} />, { useRedux: true });
expect(container).toBeInTheDocument();
});

test('should render the navigation', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
expect(screen.getByRole('navigation')).toBeInTheDocument();
});

Expand All @@ -202,7 +259,7 @@ test('should render the brand', () => {
brand: { alt, icon },
},
} = mockedProps;
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
const image = screen.getByAltText(alt);
expect(image).toHaveAttribute('src', icon);
});
Expand All @@ -212,7 +269,7 @@ test('should render all the top navbar menu items', () => {
const {
data: { menu },
} = mockedProps;
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
menu.forEach(item => {
expect(screen.getByText(item.label)).toBeInTheDocument();
});
Expand All @@ -223,7 +280,7 @@ test('should render the top navbar child menu items', async () => {
const {
data: { menu },
} = mockedProps;
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
const sources = screen.getByText('Sources');
userEvent.hover(sources);
const datasets = await screen.findByText('Datasets');
Expand All @@ -237,7 +294,7 @@ test('should render the top navbar child menu items', async () => {

test('should render the dropdown items', async () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...notanonProps} />);
render(<Menu {...notanonProps} />, { useRedux: true });
const dropdown = screen.getByTestId('new-dropdown-icon');
userEvent.hover(dropdown);
// todo (philip): test data submenu
Expand All @@ -263,14 +320,14 @@ test('should render the dropdown items', async () => {

test('should render the Settings', async () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
const settings = await screen.findByText('Settings');
expect(settings).toBeInTheDocument();
});

test('should render the Settings menu item', async () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
userEvent.hover(screen.getByText('Settings'));
const label = await screen.findByText('Security');
expect(label).toBeInTheDocument();
Expand All @@ -281,21 +338,21 @@ test('should render the Settings dropdown child menu items', async () => {
const {
data: { settings },
} = mockedProps;
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
userEvent.hover(screen.getByText('Settings'));
const listUsers = await screen.findByText('List Users');
expect(listUsers).toHaveAttribute('href', settings[0].childs[0].url);
});

test('should render the plus menu (+) when user is not anonymous', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...notanonProps} />);
render(<Menu {...notanonProps} />, { useRedux: true });
expect(screen.getByTestId('new-dropdown')).toBeInTheDocument();
});

test('should NOT render the plus menu (+) when user is anonymous', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
expect(screen.queryByTestId('new-dropdown')).not.toBeInTheDocument();
});

Expand All @@ -307,7 +364,7 @@ test('should render the user actions when user is not anonymous', async () => {
},
} = mockedProps;

render(<Menu {...notanonProps} />);
render(<Menu {...notanonProps} />, { useRedux: true });
userEvent.hover(screen.getByText('Settings'));
const user = await screen.findByText('User');
expect(user).toBeInTheDocument();
Expand All @@ -321,7 +378,7 @@ test('should render the user actions when user is not anonymous', async () => {

test('should NOT render the user actions when user is anonymous', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
expect(screen.queryByText('User')).not.toBeInTheDocument();
});

Expand All @@ -333,7 +390,7 @@ test('should render the Profile link when available', async () => {
},
} = mockedProps;

render(<Menu {...notanonProps} />);
render(<Menu {...notanonProps} />, { useRedux: true });

userEvent.hover(screen.getByText('Settings'));
const profile = await screen.findByText('Profile');
Expand All @@ -348,7 +405,7 @@ test('should render the About section and version_string, sha or build_number wh
},
} = mockedProps;

render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
userEvent.hover(screen.getByText('Settings'));
const about = await screen.findByText('About');
const version = await screen.findByText(`Version: ${version_string}`);
Expand All @@ -367,7 +424,7 @@ test('should render the Documentation link when available', async () => {
navbar_right: { documentation_url },
},
} = mockedProps;
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
userEvent.hover(screen.getByText('Settings'));
const doc = await screen.findByTitle('Documentation');
expect(doc).toHaveAttribute('href', documentation_url);
Expand All @@ -381,7 +438,7 @@ test('should render the Bug Report link when available', async () => {
},
} = mockedProps;

render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
const bugReport = await screen.findByTitle('Report a bug');
expect(bugReport).toHaveAttribute('href', bug_report_url);
});
Expand All @@ -394,19 +451,19 @@ test('should render the Login link when user is anonymous', () => {
},
} = mockedProps;

render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
const login = screen.getByText('Login');
expect(login).toHaveAttribute('href', user_login_url);
});

test('should render the Language Picker', () => {
useSelectorMock.mockReturnValue({ roles: user.roles });
render(<Menu {...mockedProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
expect(screen.getByLabelText('Languages')).toBeInTheDocument();
});

test('should hide create button without proper roles', () => {
useSelectorMock.mockReturnValue({ roles: [] });
render(<Menu {...notanonProps} />);
render(<Menu {...mockedProps} />, { useRedux: true });
expect(screen.queryByTestId('new-dropdown')).not.toBeInTheDocument();
});
2 changes: 1 addition & 1 deletion superset-frontend/src/views/components/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ interface MenuObjectChildProps {
index?: number;
url?: string;
isFrontendRoute?: boolean;
perm?: string;
perm?: string | boolean;
view?: string;
}

Expand Down
Loading

0 comments on commit 209e3f4

Please sign in to comment.