Unverified Commit 994eb88c authored by Daniel's avatar Daniel Committed by GitHub

Hide the 'explore' button when not enabled for a particular database (#366)

* Hide the 'explore' button when not enabled for a particular database
* Added tests for explore button
* Added config-utils for explore url generation
parent 075386da
import * as React from 'react'; import * as React from 'react';
import AppConfig from 'config/config';
import { logClick } from 'ducks/utilMethods'; import { logClick } from 'ducks/utilMethods';
import { TableMetadata } from 'interfaces'; import { TableMetadata } from 'interfaces';
import { exploreEnabled, generateExploreUrl } from 'config/config-utils';
export interface ExploreButtonProps { export interface ExploreButtonProps {
tableData: TableMetadata; tableData: TableMetadata;
} }
export class ExploreButton extends React.Component<ExploreButtonProps> { class ExploreButton extends React.Component<ExploreButtonProps> {
constructor(props) { constructor(props) {
super(props); super(props);
} }
generateUrl() {
const tableData = this.props.tableData;
const partition = tableData.partition;
if (partition.is_partitioned) {
return AppConfig.tableProfile.exploreUrlGenerator(
tableData.database, tableData.cluster, tableData.schema, tableData.name, partition.key, partition.value);
}
return AppConfig.tableProfile.exploreUrlGenerator(
tableData.database, tableData.cluster, tableData.schema, tableData.name);
}
render() { render() {
if (!AppConfig.tableProfile.isExploreEnabled) { const url = generateExploreUrl(this.props.tableData);
if (!url || !exploreEnabled()) {
return null; return null;
} }
return ( return (
<a <a
className="btn btn-default btn-lg" className="btn btn-default btn-lg"
href={ this.generateUrl() } href={ url }
role="button" role="button"
target="_blank" target="_blank"
id="explore-sql" id="explore-sql"
......
import * as React from 'react';
import { shallow } from 'enzyme';
import * as ConfigUtils from 'config/config-utils';
import ExploreButton from 'components/TableDetail/ExploreButton';
import { TableMetadata } from 'interfaces/TableMetadata';
import { logClick } from 'ducks/utilMethods';
let mockExploreEnabled = true;
let mockExploreUrl = 'https://test-website.com';
jest.mock('config/config-utils', () => (
{
exploreEnabled: () => { return mockExploreEnabled },
generateExploreUrl: () => { return mockExploreUrl }
}
));
const generateExploreUrlSpy = jest.spyOn(ConfigUtils, "generateExploreUrl");
describe('ExploreButton', () => {
const setup = (tableDataOverrides?: Partial<TableMetadata>) => {
const props = {
tableData: {
badges: [],
cluster: 'cluster',
columns: [],
database: 'database',
is_editable: false,
is_view: false,
key: '',
schema: 'schema',
name: 'table_name',
last_updated_timestamp: 12321312321,
description: '',
table_writer: { application_url: '', description: '', id: '', name: '' },
partition: {
is_partitioned: true,
key: 'partition_key',
value: 'partition_value',
},
table_readers: [],
source: { source: '', source_type: '' },
watermarks: [],
...tableDataOverrides,
},
};
const wrapper = shallow<ExploreButton>(<ExploreButton {...props } />)
return { props, wrapper };
};
describe('generateUrl', () => {
});
describe('render', () => {
beforeEach(() => {
mockExploreEnabled = true;
mockExploreUrl = 'https://test-website.com';
});
it('calls url generator with the partition value and key, if partitioned', () => {
const { props, wrapper } = setup();
wrapper.instance().render();
expect(generateExploreUrlSpy).toHaveBeenCalledWith(props.tableData);
});
it('returns null if explore is not enabled', () => {
mockExploreEnabled = false;
const { props, wrapper } = setup();
expect(wrapper.instance().render()).toBeNull();
});
it('returns null if the generated url is empty', () => {
const { props, wrapper } = setup();
mockExploreUrl = '';
expect(wrapper.instance().render()).toBeNull();
});
it('renders a link to the explore URL', () => {
const { props, wrapper } = setup();
expect(wrapper.find('a').props()).toMatchObject({
href: mockExploreUrl,
target: "_blank",
id: "explore-sql",
onClick: logClick,
});
});
});
});
import AppConfig from 'config/config'; import AppConfig from 'config/config';
import { BadgeStyleConfig, BadgeStyle } from 'config/config-types'; import { BadgeStyleConfig, BadgeStyle } from 'config/config-types';
import { TableMetadata } from 'interfaces/TableMetadata';
export const DEFAULT_DATABASE_ICON_CLASS = 'icon-database icon-color'; export const DEFAULT_DATABASE_ICON_CLASS = 'icon-database icon-color';
...@@ -81,3 +82,26 @@ export function showAllTags(): boolean { ...@@ -81,3 +82,26 @@ export function showAllTags(): boolean {
export function getCuratedTags(): string[] { export function getCuratedTags(): string[] {
return AppConfig.browse.curatedTags; return AppConfig.browse.curatedTags;
} }
/**
* Returns whether to enable the table `explore` feature
*/
export function exploreEnabled(): boolean {
return AppConfig.tableProfile.isExploreEnabled;
}
/**
* Generates the explore URL from a table metadata object
*
* @param tableData
*/
export function generateExploreUrl(tableData: TableMetadata): string {
const partition = tableData.partition;
if (partition.is_partitioned) {
return AppConfig.tableProfile.exploreUrlGenerator(
tableData.database, tableData.cluster, tableData.schema, tableData.name, partition.key, partition.value);
}
return AppConfig.tableProfile.exploreUrlGenerator(
tableData.database, tableData.cluster, tableData.schema, tableData.name);
}
...@@ -88,3 +88,68 @@ describe('getCuratedTags', () => { ...@@ -88,3 +88,68 @@ describe('getCuratedTags', () => {
expect(ConfigUtils.getCuratedTags()).toBe(AppConfig.browse.curatedTags); expect(ConfigUtils.getCuratedTags()).toBe(AppConfig.browse.curatedTags);
}); });
}); });
describe('exploreEnabled', () => {
it('returns whether the explore function is enabled', () => {
AppConfig.tableProfile.isExploreEnabled = true;
expect(ConfigUtils.exploreEnabled()).toBe(AppConfig.tableProfile.isExploreEnabled);
AppConfig.tableProfile.isExploreEnabled = false;
expect(ConfigUtils.exploreEnabled()).toBe(AppConfig.tableProfile.isExploreEnabled);
});
});
describe('generateExploreUrl', () => {
const tableData = {
badges: [],
cluster: 'cluster',
columns: [],
database: 'database',
is_editable: false,
is_view: false,
key: '',
schema: 'schema',
name: 'table_name',
last_updated_timestamp: 12321312312,
description: '',
table_writer: { application_url: '', description: '', id: '', name: '' },
partition: {
is_partitioned: true,
key: 'partition_key',
value: 'partition_value',
},
table_readers: [],
source: { source: '', source_type: '' },
watermarks: [],
};
it('calls `exploreUrlGenerator` with table metadata', () => {
const exploreUrlGeneratorSpy = jest.spyOn(AppConfig.tableProfile, 'exploreUrlGenerator');
ConfigUtils.generateExploreUrl(tableData);
expect(exploreUrlGeneratorSpy).toBeCalledWith(
tableData.database,
tableData.cluster,
tableData.schema,
tableData.name,
tableData.partition.key,
tableData.partition.value);
});
it('excludes partition data if it does not exist', () => {
const mockTableData = {
...tableData,
partition: {
is_partitioned: false,
},
};
const exploreUrlGeneratorSpy = jest.spyOn(AppConfig.tableProfile, 'exploreUrlGenerator');
ConfigUtils.generateExploreUrl(mockTableData);
expect(exploreUrlGeneratorSpy).toBeCalledWith(
mockTableData.database,
mockTableData.cluster,
mockTableData.schema,
mockTableData.name);
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment