Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Task: Improve test coverage #1434

Merged
merged 26 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b9f4fe2
add test coverage for root app
Onokaev Dec 7, 2021
0f09485
add react testing library to dev dependencies
Onokaev Dec 7, 2021
2b6d3d9
added tests
Onokaev Dec 8, 2021
bbb26ef
coverage currently 53%
Onokaev Dec 14, 2021
d38ff95
test coverage at 70%
Onokaev Jan 10, 2022
b13d902
fix linting errors
Onokaev Jan 10, 2022
81495d9
Merge branch 'dev' into task/improve-test-coverage
Onokaev Jan 10, 2022
a71a9c8
update coverage
Onokaev Feb 4, 2022
938ee06
clean up tests
Onokaev Feb 8, 2022
a198bde
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 8, 2022
a80a4ed
fix augloop file path
Onokaev Feb 8, 2022
b836d99
fix linting error
Onokaev Feb 8, 2022
d6b0f15
fix linting error
Onokaev Feb 8, 2022
eb86f38
restore workflow
Onokaev Feb 8, 2022
b10e0d4
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 15, 2022
778e842
remove unnecessary mocks
Onokaev Feb 15, 2022
8a85622
mock components with jest
Onokaev Feb 16, 2022
87a9c0e
fix code smells
Onokaev Feb 16, 2022
b403514
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 16, 2022
3af4d72
fix failing tests
Onokaev Feb 16, 2022
68a581e
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 17, 2022
e812dd7
merge with dev
Onokaev Feb 17, 2022
bc99704
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 18, 2022
a8e5136
fix merge conflicts
Onokaev Feb 18, 2022
e58d2c9
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 18, 2022
32196eb
Merge branch 'dev' into task/improve-test-coverage
Onokaev Feb 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions __mocks__/QueryInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { IDropdownOption, Dropdown } from '@fluentui/react';
import React from 'react';
import { injectIntl } from 'react-intl';
import { useDispatch, useSelector } from 'react-redux';
import { httpMethods, IQueryInputProps } from '../src/types/query-runner';

import { IRootState } from '../src/types/root';
import { setSampleQuery } from '../src/app/services/actions/query-input-action-creators';
import { getStyleFor } from '../src/app/utils/http-methods.utils';
import { parseSampleUrl } from '../src/app/utils/sample-url-generation';
import { translateMessage } from '../src/app/utils/translate-messages';
import SubmitButton from '../src/app/views/common/submit-button/SubmitButton';
import { queryRunnerStyles } from '../src/app/views/query-runner/QueryRunner.styles';
import { AutoComplete } from '../src/app/views/query-runner/query-input/auto-complete';

const QueryInput = (props: IQueryInputProps) => {
const {
handleOnRunQuery,
handleOnMethodChange,
handleOnVersionChange
} = props;

const dispatch = useDispatch();


const urlVersions: IDropdownOption[] = [
{ key: 'v1.0', text: 'v1.0' },
{ key: 'beta', text: 'beta' }
];

const { sampleQuery, authToken,
isLoadingData: submitting } = useSelector((state: IRootState) => state);
const authenticated = !!authToken.token;

const showError = !authenticated && sampleQuery.selectedVerb !== 'GET';
const verbSelector: any = queryRunnerStyles().verbSelector;
verbSelector.title = {
...verbSelector.title,
background: getStyleFor(sampleQuery.selectedVerb)
};

const contentChanged = (value: string) => {
const query = { ...sampleQuery, ...{ sampleUrl: value } };
changeUrlVersion(value);
dispatch(setSampleQuery(query));
};

const changeUrlVersion = (newUrl: string) => {
const query = { ...sampleQuery };
const { queryVersion: newQueryVersion } = parseSampleUrl(newUrl);
const { queryVersion: oldQueryVersion } = parseSampleUrl(query.sampleUrl);

if (newQueryVersion !== oldQueryVersion) {
if (newQueryVersion === 'v1.0' || newQueryVersion === 'beta') {
const sampleQueryToSet = { ...query };
sampleQueryToSet.selectedVersion = newQueryVersion;
sampleQueryToSet.sampleUrl = newUrl;
dispatch(setSampleQuery(sampleQueryToSet));
}
}
}

const runQuery = () => {
if (!sampleQuery.sampleUrl) {
return;
}
// allows the state to be populated with the new url before running it
setTimeout(() => {
handleOnRunQuery();
}, 500);
};

return (
<div className='row'>
<div className='col-xs-12 col-lg-2'>
<Dropdown
ariaLabel={translateMessage('HTTP request method option')}
selectedKey={sampleQuery.selectedVerb}
options={httpMethods}
styles={verbSelector}
errorMessage={showError ? translateMessage('Sign in to use this method') : undefined}
onChange={(event, method) => handleOnMethodChange(method)}
/>
</div>
<div className='col-xs-12 col-lg-2'>
<Dropdown
ariaLabel={translateMessage('Microsoft Graph API Version option')}
selectedKey={sampleQuery.selectedVersion || 'v1.0'}
options={urlVersions}
onChange={(event, method) => handleOnVersionChange(method)}
/>
</div>
<div className='col-xs-12 col-lg-6'>
<AutoComplete
contentChanged={contentChanged}
runQuery={runQuery}
/>
</div>
<div className='col-xs-12 col-lg-2'>
<SubmitButton
className='run-query-button'
text={translateMessage('Run Query')}
disabled={showError || !sampleQuery.sampleUrl}
role='button'
handleOnClick={() => runQuery()}
submitting={submitting}
allowDisabledFocus={true}
/>
</div>
</div>)
}

// @ts-ignore
const IntlQueryInput = injectIntl(QueryInput);
// @ts-ignore
export default IntlQueryInput;
247 changes: 247 additions & 0 deletions __mocks__/Request.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
import {
getId,
Icon,
Pivot,
PivotItem,
TooltipHost
} from '@fluentui/react';
import { Resizable } from 're-resizable';
import React, { Component, CSSProperties } from 'react';
import { injectIntl } from 'react-intl';
import { connect } from 'react-redux';
import { bindActionCreators, Dispatch } from 'redux';

import { telemetry } from '../src/telemetry';
import { Mode } from '../src/types/enums';
import { IRequestComponent } from '../src/types/request';
import { IRootState } from '../src/types/root';
import { setDimensions } from '../src/app/services/actions/dimensions-action-creator';
import { translateMessage } from '../src/app/utils/translate-messages';
import { convertPxToVh, convertVhToPx } from '../src/app/views/common/dimensions-adjustment';
import { Auth } from '../src/app/views/query-runner/request/auth';
import { RequestBody } from '../src/app/views/query-runner/request/body';
import FeedbackForm from '../src/app/views/query-runner/request/feedback/FeedbackForm';
import { RequestHeaders } from '../src/app/views/query-runner/request/headers';
import { Permission } from '../src/app/views/query-runner/request/permissions';
import './request.scss';

export class Request extends Component<IRequestComponent, any> {
constructor(props: IRequestComponent) {
super(props);
this.state = {
enableShowSurvey: false,
selectedPivot: 'request-body'
}
}

private toggleCustomSurvey = (show: boolean = false) => {
this.setState({ enableShowSurvey: show });
}

private getPivotItems = (height: string) => {
const {
handleOnEditorChange,
mode,
intl: { messages }
}: any = this.props;

const heightAdjustment = 55;
const containerStyle: CSSProperties = {
height: convertVhToPx(height, heightAdjustment),
overflowY: 'hidden',
overflowX: 'hidden',
borderBottom: '1px solid #ddd'
};

const pivotItems = [
<PivotItem
key='request-body'
itemIcon='Send'
itemKey='request-body' // To be used to construct component name for telemetry data
onRenderItemLink={this.getTooltipDisplay}
ariaLabel={messages['request body']}
title={messages['request body']}
headerText={messages['request body']}
>
<div style={containerStyle}>
<RequestBody handleOnEditorChange={handleOnEditorChange} />
</div>
</PivotItem>,
<PivotItem
key='request-headers'
itemIcon='FileComment'
itemKey='request-headers'
onRenderItemLink={this.getTooltipDisplay}
ariaLabel={messages['request header']}
title={messages['request header']}
headerText={messages['request header']}
>
<div style={containerStyle}>
<RequestHeaders />
</div>
</PivotItem>,
<PivotItem
key='modify-permissions'
itemIcon='AzureKeyVault'
itemKey='modify-permissions'
onRenderItemLink={this.getTooltipDisplay}
ariaLabel={translateMessage('permissions preview')}
title={translateMessage('permissions preview')}
headerText={messages['modify permissions']}
>
<div style={containerStyle}>
<Permission />
</div>
</PivotItem>,
<PivotItem
key='feedback'
itemIcon='HeartFill'
itemKey='feedback'
onRenderItemLink={this.getTooltipDisplay}
ariaLabel={translateMessage('Feedback')}
title={translateMessage('Feedback')}
headerText={translateMessage('Feedback')}
>
</PivotItem>
];

if (mode === Mode.Complete) {
pivotItems.push(
<PivotItem
key='access-token'
itemIcon='AuthenticatorApp'
itemKey='access-token'
onRenderItemLink={this.getTooltipDisplay}
ariaLabel={translateMessage('Access Token')}
title={translateMessage('Access Token')}
headerText={translateMessage('Access Token')}>
<div style={containerStyle}>
<Auth />
</div>
</PivotItem>,
);
}
return pivotItems;
}

private getTooltipDisplay(link: any) {
return (
<TooltipHost
content={link.title}
id={getId()}
calloutProps={{ gapSpace: 0 }}
>
<Icon iconName={link.itemIcon} style={{ paddingRight: 5 }} />
{link.headerText}
</TooltipHost>
);
}

private handlePivotItemClick = (pivotItem?: PivotItem) => {
if (!pivotItem) {
return;
}
this.onPivotItemClick(pivotItem);
this.toggleFeedback(pivotItem);
}

private toggleFeedback = (event: any) => {
const { key } = event;
if (key && key.includes('feedback')) {
this.toggleCustomSurvey(true);
this.setState({ selectedPivot: 'request-body' })
} else {
this.setState({ selectedPivot: key })
}
}

private onPivotItemClick = (item?: PivotItem) => {
if (!item) { return; }
const tabKey = item.props.itemKey;
const { sampleQuery }: any = this.props;
if (tabKey) {
telemetry.trackTabClickEvent(tabKey, sampleQuery);
}
};

private setRequestAndResponseHeights = (requestHeight: string) => {
const heightInPx = requestHeight.replace('px', '').trim();
const requestHeightInVh = convertPxToVh(parseFloat(heightInPx)).toString();
const maxDeviceVerticalHeight = 90;
const dimen = { ...this.props.dimensions };
dimen.request.height = requestHeightInVh;
const response = maxDeviceVerticalHeight - parseFloat(requestHeightInVh.replace('vh', ''));
dimen.response.height = response + 'vh';
this.props.actions!.setDimensions(dimen);
};


public render() {
const { dimensions } = this.props;
const requestPivotItems = this.getPivotItems(dimensions.request.height);
const { selectedPivot } = this.state;
const pivot = selectedPivot.replace('.$', '');
const minHeight = 60;
const maxHeight = 800;
return (
<>
<Resizable
style={{
border: 'solid 1px #ddd',
marginBottom: 10
}}
onResize={(e: any, direction: any, ref: any) => {
if (ref && ref.style && ref.style.height) {
this.setRequestAndResponseHeights(ref.style.height);
}
}}
maxHeight={maxHeight}
minHeight={minHeight}
bounds={'window'}
size={{
height: 'inherit',
width: '100%'
}}
enable={{
bottom: true
}}
>
<div className='query-request'>
<Pivot
overflowBehavior='menu'
onLinkClick={this.handlePivotItemClick}
className='pivot-request'
selectedKey={pivot}
>
{requestPivotItems}
</Pivot>
</div>
</Resizable>
<FeedbackForm activated={this.state.enableShowSurvey} dismissSurvey={this.toggleCustomSurvey} />
</>
);
}
}

function mapStateToProps(
{ graphExplorerMode, sampleQuery, theme, sidebarProperties, dimensions }: IRootState) {
return {
mode: graphExplorerMode,
sampleBody: sampleQuery.sampleBody,
theme,
mobileScreen: !!sidebarProperties.mobileScreen,
dimensions
};
}

function mapDispatchToProps(dispatch: Dispatch) {
return {
actions: bindActionCreators({
setDimensions
}, dispatch)
};
}

// @ts-ignore
const IntlRequest = injectIntl(Request);
export default connect(mapStateToProps, mapDispatchToProps)(IntlRequest);
1 change: 1 addition & 0 deletions config/CSSStub.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = null;
Loading