Unverified Commit 603144d4 authored by Tamika Tannis's avatar Tamika Tannis Committed by GitHub

Update JIRA Issue query + TableIssue UI (#415)

* Update search query stub

* Update search query stub

* Further specify query

* Move 'isLoading' to TableIssues

* Fix python test
parent 2b67c4c4
...@@ -11,7 +11,7 @@ from amundsen_application.models.issue_results import IssueResults ...@@ -11,7 +11,7 @@ from amundsen_application.models.issue_results import IssueResults
import urllib.parse import urllib.parse
import logging import logging
SEARCH_STUB_ALL_ISSUES = 'text ~ "{table_key}" order by createdDate DESC' SEARCH_STUB_ALL_ISSUES = 'text ~ "\\"Table Key: {table_key} [PLEASE DO NOT REMOVE]\\"" order by createdDate DESC'
# this is provided by jira as the type of a bug # this is provided by jira as the type of a bug
ISSUE_TYPE_ID = 1 ISSUE_TYPE_ID = 1
ISSUE_TYPE_NAME = 'Bug' ISSUE_TYPE_NAME = 'Bug'
......
...@@ -3,11 +3,10 @@ import { connect } from 'react-redux'; ...@@ -3,11 +3,10 @@ import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { GlobalState } from 'ducks/rootReducer'; import { GlobalState } from 'ducks/rootReducer';
import LoadingSpinner from 'components/common/LoadingSpinner'; import { createIssue } from 'ducks/issue/reducer';
import { createIssue } from 'ducks/issue/reducer';
import { CreateIssueRequest } from 'ducks/issue/types'; import { CreateIssueRequest } from 'ducks/issue/types';
import './styles.scss'; import './styles.scss';
import { REPORT_DATA_ISSUE_TEXT, TABLE_OWNERS_NOTE } from './constants'; import { REPORT_DATA_ISSUE_TEXT, TABLE_OWNERS_NOTE } from './constants';
import { logClick } from 'ducks/utilMethods'; import { logClick } from 'ducks/utilMethods';
import { TableMetadata, CreateIssuePayload, NotificationPayload, NotificationType } from 'interfaces'; import { TableMetadata, CreateIssuePayload, NotificationPayload, NotificationType } from 'interfaces';
...@@ -18,20 +17,19 @@ export interface ComponentProps { ...@@ -18,20 +17,19 @@ export interface ComponentProps {
export interface DispatchFromProps { export interface DispatchFromProps {
createIssue: ( createIssue: (
createIssuePayload: CreateIssuePayload, createIssuePayload: CreateIssuePayload,
notificationPayload: NotificationPayload notificationPayload: NotificationPayload
) => CreateIssueRequest; ) => CreateIssueRequest;
} }
export interface StateFromProps { export interface StateFromProps {
isLoading: boolean; tableOwners: string[];
tableOwners: string[]; userEmail: string;
userEmail: string; tableMetadata: TableMetadata;
tableMetadata: TableMetadata;
} }
interface ReportTableIssueState { interface ReportTableIssueState {
isOpen: boolean; isOpen: boolean;
} }
export type ReportTableIssueProps = StateFromProps & DispatchFromProps & ComponentProps export type ReportTableIssueProps = StateFromProps & DispatchFromProps & ComponentProps
...@@ -47,53 +45,50 @@ export class ReportTableIssue extends React.Component<ReportTableIssueProps, Rep ...@@ -47,53 +45,50 @@ export class ReportTableIssue extends React.Component<ReportTableIssueProps, Rep
event.preventDefault(); event.preventDefault();
const form = document.getElementById("report-table-issue-form") as HTMLFormElement; const form = document.getElementById("report-table-issue-form") as HTMLFormElement;
const formData = new FormData(form); const formData = new FormData(form);
const createIssuePayload = this.getCreateIssuePayload(formData); const createIssuePayload = this.getCreateIssuePayload(formData);
const notificationPayload = this.getNotificationPayload(); const notificationPayload = this.getNotificationPayload();
this.props.createIssue(createIssuePayload, notificationPayload); this.props.createIssue(createIssuePayload, notificationPayload);
this.setState({isOpen: false }); this.setState({isOpen: false });
}; };
getCreateIssuePayload = (formData: FormData): CreateIssuePayload => { getCreateIssuePayload = (formData: FormData): CreateIssuePayload => {
const title = formData.get('title') as string; const title = formData.get('title') as string;
const description = formData.get('description') as string; const description = formData.get('description') as string;
return { return {
title, title,
description, description,
key: this.props.tableKey, key: this.props.tableKey,
} }
} }
getNotificationPayload = (): NotificationPayload => { getNotificationPayload = (): NotificationPayload => {
const { cluster, database, schema, name } = this.props.tableMetadata; const { cluster, database, schema, name } = this.props.tableMetadata;
const owners = this.props.tableOwners; const owners = this.props.tableOwners;
const resourceName = `${schema}.${name}`; const resourceName = `${schema}.${name}`;
const resourcePath = `/table_detail/${cluster}/${database}/${schema}/${name}`; const resourcePath = `/table_detail/${cluster}/${database}/${schema}/${name}`;
return { return {
recipients: owners, recipients: owners,
sender: this.props.userEmail, sender: this.props.userEmail,
notificationType: NotificationType.DATA_ISSUE_REPORTED, notificationType: NotificationType.DATA_ISSUE_REPORTED,
options: { options: {
resource_name: resourceName, resource_name: resourceName,
resource_path: resourcePath, resource_path: resourcePath,
} }
}; };
} }
toggle = (event) => { toggle = (event) => {
if (!this.state.isOpen) { if (!this.state.isOpen) {
logClick(event); logClick(event);
} }
this.setState({ isOpen: !this.state.isOpen }); this.setState({ isOpen: !this.state.isOpen });
}; };
render() { render() {
if (this.props.isLoading) {
return <LoadingSpinner />;
}
return ( return (
<> <>
<a href="javascript:void(0)" <a href="javascript:void(0)"
...@@ -130,13 +125,12 @@ export class ReportTableIssue extends React.Component<ReportTableIssueProps, Rep ...@@ -130,13 +125,12 @@ export class ReportTableIssue extends React.Component<ReportTableIssueProps, Rep
} }
} }
export const mapStateToProps = (state: GlobalState) => { export const mapStateToProps = (state: GlobalState) => {
const ownerObj = state.tableMetadata.tableOwners.owners; const ownerObj = state.tableMetadata.tableOwners.owners;
const tableOwnersEmails = Object.keys(ownerObj); const tableOwnersEmails = Object.keys(ownerObj);
const userEmail = state.user.loggedInUser.email; const userEmail = state.user.loggedInUser.email;
return { return {
userEmail, userEmail,
isLoading: state.issue.isLoading, tableOwners: tableOwnersEmails,
tableOwners: tableOwnersEmails,
tableMetadata: state.tableMetadata.tableData tableMetadata: state.tableMetadata.tableData
}; };
}; };
......
...@@ -4,30 +4,30 @@ import { shallow } from 'enzyme'; ...@@ -4,30 +4,30 @@ import { shallow } from 'enzyme';
import AppConfig from 'config/config'; import AppConfig from 'config/config';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import { import {
ComponentProps, ComponentProps,
ReportTableIssue, ReportTableIssue,
ReportTableIssueProps, ReportTableIssueProps,
mapDispatchToProps, mapDispatchToProps,
mapStateToProps, mapStateToProps,
} from '..'; } from '..';
import { NotificationType } from 'interfaces'; import { NotificationType } from 'interfaces';
const mockFormData = { const mockFormData = {
'key': 'val1', 'key': 'val1',
'title': 'title', 'title': 'title',
'description': 'description', 'description': 'description',
'resource_name': 'resource name', 'resource_name': 'resource name',
'resource_path': 'path', 'resource_path': 'path',
'owners': 'test@test.com', 'owners': 'test@test.com',
get: (key: string) => { get: (key: string) => {
return mockFormData[key]; return mockFormData[key];
} }
}; };
const mockCreateIssuePayload = { const mockCreateIssuePayload = {
key: 'key', key: 'key',
title: 'title', title: 'title',
description: 'description' description: 'description'
} }
...@@ -40,7 +40,7 @@ const mockNotificationPayload = { ...@@ -40,7 +40,7 @@ const mockNotificationPayload = {
recipients: ['owner@email'], recipients: ['owner@email'],
sender: 'user@email' sender: 'user@email'
} }
// @ts-ignore: How to mock FormData without TypeScript error? // @ts-ignore: How to mock FormData without TypeScript error?
global.FormData = () => (mockFormData); global.FormData = () => (mockFormData);
...@@ -48,17 +48,16 @@ describe('ReportTableIssue', () => { ...@@ -48,17 +48,16 @@ describe('ReportTableIssue', () => {
const setStateSpy = jest.spyOn(ReportTableIssue.prototype, 'setState'); const setStateSpy = jest.spyOn(ReportTableIssue.prototype, 'setState');
const setup = (propOverrides?: Partial<ReportTableIssueProps>) => { const setup = (propOverrides?: Partial<ReportTableIssueProps>) => {
const props: ReportTableIssueProps = { const props: ReportTableIssueProps = {
isLoading: false, createIssue: jest.fn(),
createIssue: jest.fn(), tableKey: 'key',
tableKey: 'key',
tableName: 'name', tableName: 'name',
tableOwners: ['owner@email'], tableOwners: ['owner@email'],
tableMetadata: {...globalState.tableMetadata.tableData, tableMetadata: {...globalState.tableMetadata.tableData,
schema: 'schema', schema: 'schema',
name: 'table_name', name: 'table_name',
cluster: 'cluster', cluster: 'cluster',
database: 'database'}, database: 'database'},
userEmail: 'user@email', userEmail: 'user@email',
...propOverrides ...propOverrides
}; };
const wrapper = shallow<ReportTableIssue>(<ReportTableIssue {...props} />); const wrapper = shallow<ReportTableIssue>(<ReportTableIssue {...props} />);
...@@ -69,11 +68,11 @@ describe('ReportTableIssue', () => { ...@@ -69,11 +68,11 @@ describe('ReportTableIssue', () => {
it('Renders loading spinner if not ready', () => { it('Renders loading spinner if not ready', () => {
const { props, wrapper } = setup(); const { props, wrapper } = setup();
expect(wrapper.find('.loading-spinner')).toBeTruthy(); expect(wrapper.find('.loading-spinner')).toBeTruthy();
}); });
it('Renders modal if open', () => { it('Renders modal if open', () => {
const { props, wrapper } = setup({isLoading: false}); const { props, wrapper } = setup();
wrapper.setState({isOpen: true}); wrapper.setState({isOpen: true});
expect(wrapper.find('.report-table-issue-modal')).toBeTruthy(); expect(wrapper.find('.report-table-issue-modal')).toBeTruthy();
}); });
...@@ -87,37 +86,37 @@ describe('ReportTableIssue', () => { ...@@ -87,37 +86,37 @@ describe('ReportTableIssue', () => {
expect(setStateSpy).toHaveBeenCalledWith({ isOpen: !previsOpenState }); expect(setStateSpy).toHaveBeenCalledWith({ isOpen: !previsOpenState });
}); });
}); });
describe('submitForm', () => { describe('submitForm', () => {
it ('calls createIssue with mocked form data', () => { it ('calls createIssue with mocked form data', () => {
const { props, wrapper } = setup(); const { props, wrapper } = setup();
// @ts-ignore: mocked events throw type errors // @ts-ignore: mocked events throw type errors
wrapper.instance().submitForm({ preventDefault: jest.fn(), wrapper.instance().submitForm({ preventDefault: jest.fn(),
currentTarget: {id: 'id', nodeName: 'button'} }); currentTarget: {id: 'id', nodeName: 'button'} });
expect(props.createIssue).toHaveBeenCalledWith( expect(props.createIssue).toHaveBeenCalledWith(
mockCreateIssuePayload, mockCreateIssuePayload,
mockNotificationPayload); mockNotificationPayload);
expect(wrapper.state().isOpen).toBe(false); expect(wrapper.state().isOpen).toBe(false);
}); });
it ('calls sets isOpen to false', () => { it ('calls sets isOpen to false', () => {
const { props, wrapper } = setup(); const { props, wrapper } = setup();
// @ts-ignore: mocked events throw type errors // @ts-ignore: mocked events throw type errors
wrapper.instance().submitForm({ preventDefault: jest.fn(), wrapper.instance().submitForm({ preventDefault: jest.fn(),
currentTarget: {id: 'id', nodeName: 'button'} }); currentTarget: {id: 'id', nodeName: 'button'} });
expect(wrapper.state().isOpen).toBe(false); expect(wrapper.state().isOpen).toBe(false);
}); });
}); });
describe('mapDispatchToProps', () => { describe('mapDispatchToProps', () => {
let dispatch; let dispatch;
let props; let props;
beforeAll(() => { beforeAll(() => {
dispatch = jest.fn(() => Promise.resolve()); dispatch = jest.fn(() => Promise.resolve());
props = mapDispatchToProps(dispatch); props = mapDispatchToProps(dispatch);
}); });
it('sets getIssues on the props', () => { it('sets getIssues on the props', () => {
expect(props.createIssue).toBeInstanceOf(Function); expect(props.createIssue).toBeInstanceOf(Function);
}); });
...@@ -128,10 +127,6 @@ describe('ReportTableIssue', () => { ...@@ -128,10 +127,6 @@ describe('ReportTableIssue', () => {
beforeAll(() => { beforeAll(() => {
result = mapStateToProps(globalState); result = mapStateToProps(globalState);
}); });
});
it('sets isLoading on the props', () => { });
expect(result.isLoading).toEqual(globalState.issue.isLoading); });
});
});
});
});
...@@ -3,30 +3,32 @@ import { GlobalState } from 'ducks/rootReducer'; ...@@ -3,30 +3,32 @@ import { GlobalState } from 'ducks/rootReducer';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { Issue } from 'interfaces'; import { Issue } from 'interfaces';
import { getIssues } from 'ducks/issue/reducer'; import { getIssues } from 'ducks/issue/reducer';
import { logClick } from 'ducks/utilMethods'; import { logClick } from 'ducks/utilMethods';
import { GetIssuesRequest } from 'ducks/issue/types'; import { GetIssuesRequest } from 'ducks/issue/types';
import LoadingSpinner from 'components/common/LoadingSpinner';
import ReportTableIssue from 'components/TableDetail/ReportTableIssue'; import ReportTableIssue from 'components/TableDetail/ReportTableIssue';
import { NO_DATA_ISSUES_TEXT } from './constants'; import { NO_DATA_ISSUES_TEXT } from './constants';
import './styles.scss'; import './styles.scss';
export interface StateFromProps { export interface StateFromProps {
issues: Issue[]; issues: Issue[];
total: number; total: number;
allIssuesUrl: string; allIssuesUrl: string;
isLoading: boolean;
} }
export interface DispatchFromProps { export interface DispatchFromProps {
getIssues: (key: string) => GetIssuesRequest; getIssues: (key: string) => GetIssuesRequest;
} }
export interface ComponentProps { export interface ComponentProps {
tableKey: string; tableKey: string;
tableName: string; tableName: string;
} }
export type TableIssueProps = StateFromProps & DispatchFromProps & ComponentProps; export type TableIssueProps = StateFromProps & DispatchFromProps & ComponentProps;
export class TableIssues extends React.Component<TableIssueProps> { export class TableIssues extends React.Component<TableIssueProps> {
constructor(props) { constructor(props) {
...@@ -52,12 +54,12 @@ export class TableIssues extends React.Component<TableIssueProps> { ...@@ -52,12 +54,12 @@ export class TableIssues extends React.Component<TableIssueProps> {
<span className="issue-title-name"> <span className="issue-title-name">
{ issue.title } { issue.title }
</span> </span>
</span> </span>
<span className="table-issue-status"> <span className="table-issue-status">
{issue.status} {issue.status}
</span> </span>
</div> </div>
); );
} }
renderMoreIssuesMessage = (count: number, url: string) => { renderMoreIssuesMessage = (count: number, url: string) => {
...@@ -65,21 +67,21 @@ export class TableIssues extends React.Component<TableIssueProps> { ...@@ -65,21 +67,21 @@ export class TableIssues extends React.Component<TableIssueProps> {
<span className="table-more-issues" key="more-issue-link"> <span className="table-more-issues" key="more-issue-link">
<a id="more-issues-link" className="table-issue-more-issues" target="_blank" href={url} onClick={logClick}> <a id="more-issues-link" className="table-issue-more-issues" target="_blank" href={url} onClick={logClick}>
View all {count} issues View all {count} issues
</a> </a>
| |
{ this.renderReportIssueLink() } { this.renderReportIssueLink() }
</span> </span>
); );
} }
renderReportIssueLink = () => { renderReportIssueLink = () => {
return ( return (
<div className="table-report-new-issue"> <div className="table-report-new-issue">
<ReportTableIssue tableKey={ this.props.tableKey } tableName={ this.props.tableName }/> <ReportTableIssue tableKey={ this.props.tableKey } tableName={ this.props.tableName }/>
</div> </div>
); );
} }
renderIssueTitle = () => { renderIssueTitle = () => {
return ( return (
<div className="section-title title-3"> <div className="section-title title-3">
...@@ -89,6 +91,17 @@ export class TableIssues extends React.Component<TableIssueProps> { ...@@ -89,6 +91,17 @@ export class TableIssues extends React.Component<TableIssueProps> {
} }
render() { render() {
if (this.props.isLoading) {
return (
<div>
{this.renderIssueTitle()}
<div className="table-issues">
<LoadingSpinner />
</div>
</div>
)
}
if (this.props.issues.length === 0) { if (this.props.issues.length === 0) {
return ( return (
<div> <div>
...@@ -117,9 +130,10 @@ export class TableIssues extends React.Component<TableIssueProps> { ...@@ -117,9 +130,10 @@ export class TableIssues extends React.Component<TableIssueProps> {
export const mapStateToProps = (state: GlobalState) => { export const mapStateToProps = (state: GlobalState) => {
return { return {
issues: state.issue.issues, issues: state.issue.issues,
total: state.issue.total, total: state.issue.total,
allIssuesUrl: state.issue.allIssuesUrl allIssuesUrl: state.issue.allIssuesUrl,
isLoading: state.issue.isLoading,
}; };
}; };
......
...@@ -8,11 +8,11 @@ ...@@ -8,11 +8,11 @@
height: 40px; height: 40px;
margin: 8px 0; margin: 8px 0;
padding: 8px 16px; padding: 8px 16px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
.table-issue-link { .table-issue-link {
margin-right: $spacer-1; margin-right: $spacer-1;
min-width: fit-content; min-width: fit-content;
} }
.issue-title-name { .issue-title-name {
...@@ -33,15 +33,15 @@ ...@@ -33,15 +33,15 @@
margin-left: $spacer-2; margin-left: $spacer-2;
} }
.table-issue-priority { .table-issue-priority {
margin-right: $spacer-1; margin-right: $spacer-1;
border: 1px solid $rose80; border: 1px solid $rose80;
border-radius: 5px; border-radius: 5px;
padding: 1px 2px; padding: 1px 2px;
flex: none; flex: none;
} }
.blocker { .blocker {
color: $priority-text-blocker; color: $priority-text-blocker;
// default is $rose80 // default is $rose80
background-color: rgba($priority-bg-color, 1); background-color: rgba($priority-bg-color, 1);
} }
.critical { .critical {
...@@ -53,16 +53,19 @@ ...@@ -53,16 +53,19 @@
.minor { .minor {
background-color: rgba($priority-bg-color, .1); background-color: rgba($priority-bg-color, .1);
} }
.loading-spinner {
margin-top: auto;
}
} }
.table-issue-more-issues { .table-issue-more-issues {
margin-bottom: $spacer-1; margin-bottom: $spacer-1;
margin-right: $spacer-1; margin-right: $spacer-1;
} }
.table-more-issues { .table-more-issues {
display: flex; display: flex;
font-size: 16px; font-size: 16px;
} }
.table-report-new-issue { .table-report-new-issue {
margin-bottom: $spacer-1; margin-bottom: $spacer-1;
margin-left: $spacer-1; margin-left: $spacer-1;
} }
...@@ -5,10 +5,10 @@ import { shallow } from 'enzyme'; ...@@ -5,10 +5,10 @@ import { shallow } from 'enzyme';
import AppConfig from 'config/config'; import AppConfig from 'config/config';
import globalState from 'fixtures/globalState'; import globalState from 'fixtures/globalState';
import { import {
TableIssues, TableIssues,
TableIssueProps, TableIssueProps,
mapStateToProps, mapStateToProps,
mapDispatchToProps mapDispatchToProps
} from '..'; } from '..';
...@@ -18,85 +18,91 @@ import ReportTableIssue from 'components/TableDetail/ReportTableIssue'; ...@@ -18,85 +18,91 @@ import ReportTableIssue from 'components/TableDetail/ReportTableIssue';
describe ('TableIssues', ()=> { describe ('TableIssues', ()=> {
const setStateSpy = jest.spyOn(TableIssues.prototype, 'setState'); const setStateSpy = jest.spyOn(TableIssues.prototype, 'setState');
const setup = (propOverrides?: Partial<TableIssueProps>) => { const setup = (propOverrides?: Partial<TableIssueProps>) => {
const props: TableIssueProps = { const props: TableIssueProps = {
issues: [], isLoading: false,
issues: [],
tableKey: 'key', tableKey: 'key',
tableName: 'tableName', tableName: 'tableName',
total: 0, total: 0,
allIssuesUrl: 'testUrl', allIssuesUrl: 'testUrl',
getIssues: jest.fn(), getIssues: jest.fn(),
...propOverrides ...propOverrides
}; };
const wrapper = shallow<TableIssues>(<TableIssues {...props} />); const wrapper = shallow<TableIssues>(<TableIssues {...props} />);
return { props, wrapper }; return { props, wrapper };
} }
describe('render', () => { describe('render', () => {
beforeAll(() => { beforeAll(() => {
AppConfig.issueTracking.enabled = true; AppConfig.issueTracking.enabled = true;
}); });
it('renders LoadingSpinner if loading', () => {
const { props, wrapper } = setup({ isLoading: true });
expect(wrapper.find('LoadingSpinner').exists()).toBe(true);
});
it('renders text if no issues', () => { it('renders text if no issues', () => {
const { props, wrapper } = setup({ issues: [] }); const { props, wrapper } = setup({ issues: [] });
expect(wrapper.find('.issue-banner').text()).toEqual(NO_DATA_ISSUES_TEXT); expect(wrapper.find('.issue-banner').text()).toEqual(NO_DATA_ISSUES_TEXT);
}); });
it('renders issues if they exist', () => { it('renders issues if they exist', () => {
AppConfig.issueTracking.enabled = true; AppConfig.issueTracking.enabled = true;
const { props, wrapper } = setup({ issues: [{ const { props, wrapper } = setup({ issues: [{
issue_key: 'issue_key', issue_key: 'issue_key',
title: 'title', title: 'title',
url: 'http://url', url: 'http://url',
status: 'Open', status: 'Open',
priority_display_name: 'P2', priority_display_name: 'P2',
priority_name: 'major' priority_name: 'major'
}]}); }]});
expect(wrapper.find('.table-issue-link').text()).toEqual('issue_key'); expect(wrapper.find('.table-issue-link').text()).toEqual('issue_key');
expect(wrapper.find('.issue-title-name').text()).toContain('title'); expect(wrapper.find('.issue-title-name').text()).toContain('title');
expect(wrapper.find('.table-issue-status').text()).toContain('Open'); expect(wrapper.find('.table-issue-status').text()).toContain('Open');
expect(wrapper.find('.table-issue-priority').text()).toContain('P2'); expect(wrapper.find('.table-issue-priority').text()).toContain('P2');
}); });
it('renders no link to issues if no issues', () => { it('renders no link to issues if no issues', () => {
const { props, wrapper } = setup({ issues: [], const { props, wrapper } = setup({ issues: [],
total: 0, total: 0,
allIssuesUrl: null allIssuesUrl: null
}); });
expect(wrapper.find('.table-issue-more-issues').length).toEqual(0); expect(wrapper.find('.table-issue-more-issues').length).toEqual(0);
}); });
it('renders link if there are issues', () => { it('renders link if there are issues', () => {
const { props, wrapper } = setup({ issues: [{ const { props, wrapper } = setup({ issues: [{
issue_key: 'issue_key', issue_key: 'issue_key',
title: 'title', title: 'title',
url: 'http://url', url: 'http://url',
status: 'Open', status: 'Open',
priority_display_name: 'P2', priority_display_name: 'P2',
priority_name: 'Major' priority_name: 'Major'
}], }],
total: 1, total: 1,
allIssuesUrl: 'url' allIssuesUrl: 'url'
}); });
expect(wrapper.find('.table-issue-more-issues').text()).toEqual('View all 1 issues'); expect(wrapper.find('.table-issue-more-issues').text()).toEqual('View all 1 issues');
}); });
}); });
describe('mapDispatchToProps', () => { describe('mapDispatchToProps', () => {
let dispatch; let dispatch;
let props; let props;
beforeAll(() => { beforeAll(() => {
dispatch = jest.fn(() => Promise.resolve()); dispatch = jest.fn(() => Promise.resolve());
props = mapDispatchToProps(dispatch); props = mapDispatchToProps(dispatch);
}); });
it('sets getIssues on the props', () => { it('sets getIssues on the props', () => {
expect(props.getIssues).toBeInstanceOf(Function); expect(props.getIssues).toBeInstanceOf(Function);
}); });
}); });
describe('mapStateToProps', () => { describe('mapStateToProps', () => {
let result; let result;
beforeAll(() => { beforeAll(() => {
...@@ -104,7 +110,11 @@ describe ('TableIssues', ()=> { ...@@ -104,7 +110,11 @@ describe ('TableIssues', ()=> {
}); });
it('sets issues on the props', () => { it('sets issues on the props', () => {
expect(result.issues).toEqual(globalState.issue.issues); expect(result.issues).toEqual(globalState.issue.issues);
}); });
});
}); it('sets isLoading on the props', () => {
expect(result.isLoading).toEqual(globalState.issue.isLoading);
});
});
});
...@@ -3,7 +3,7 @@ from unittest.mock import Mock ...@@ -3,7 +3,7 @@ from unittest.mock import Mock
import flask import flask
import unittest import unittest
from amundsen_application.proxy.issue_tracker_clients.issue_exceptions import IssueConfigurationException from amundsen_application.proxy.issue_tracker_clients.issue_exceptions import IssueConfigurationException
from amundsen_application.proxy.issue_tracker_clients.jira_client import JiraClient from amundsen_application.proxy.issue_tracker_clients.jira_client import JiraClient, SEARCH_STUB_ALL_ISSUES
from amundsen_application.models.data_issue import DataIssue from amundsen_application.models.data_issue import DataIssue
from jira import JIRAError from jira import JIRAError
from typing import Dict, List from typing import Dict, List
...@@ -101,7 +101,7 @@ class JiraClientTest(unittest.TestCase): ...@@ -101,7 +101,7 @@ class JiraClientTest(unittest.TestCase):
self.assertEqual(results.issues[0], self.mock_issue) self.assertEqual(results.issues[0], self.mock_issue)
self.assertEqual(results.total, self.mock_jira_issues.total) self.assertEqual(results.total, self.mock_jira_issues.total)
mock_JIRA_client.return_value.search_issues.assert_called_with( mock_JIRA_client.return_value.search_issues.assert_called_with(
'text ~ "key" order by createdDate DESC', SEARCH_STUB_ALL_ISSUES.format(table_key="key"),
maxResults=3) maxResults=3)
@unittest.mock.patch('amundsen_application.proxy.issue_tracker_clients.jira_client.JIRA') @unittest.mock.patch('amundsen_application.proxy.issue_tracker_clients.jira_client.JIRA')
......
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