import { withRouter, WithRouterProps } from 'react-router'; | import { withRouter, WithRouterProps } from 'react-router'; | ||||
import ListFooter from 'sonar-ui-common/components/controls/ListFooter'; | import ListFooter from 'sonar-ui-common/components/controls/ListFooter'; | ||||
import SearchBox from 'sonar-ui-common/components/controls/SearchBox'; | import SearchBox from 'sonar-ui-common/components/controls/SearchBox'; | ||||
import BackIcon from 'sonar-ui-common/components/icons/BackIcon'; | |||||
import { translate } from 'sonar-ui-common/helpers/l10n'; | import { translate } from 'sonar-ui-common/helpers/l10n'; | ||||
import { | import { | ||||
addSideBarClass, | addSideBarClass, | ||||
getAppFacet, | getAppFacet, | ||||
getOpen, | getOpen, | ||||
getServerFacet, | getServerFacet, | ||||
hasRuleKey, | |||||
OpenFacets, | OpenFacets, | ||||
parseQuery, | parseQuery, | ||||
Query, | Query, | ||||
referencedRepositories: T.Dict<{ key: string; language: string; name: string }>; | referencedRepositories: T.Dict<{ key: string; language: string; name: string }>; | ||||
rules: T.Rule[]; | rules: T.Rule[]; | ||||
selected?: string; | selected?: string; | ||||
usingPermalink?: boolean; | |||||
} | } | ||||
export class App extends React.PureComponent<Props, State> { | export class App extends React.PureComponent<Props, State> { | ||||
const openRule = this.getOpenRule(nextProps, rules); | const openRule = this.getOpenRule(nextProps, rules); | ||||
return { | return { | ||||
openRule, | openRule, | ||||
usingPermalink: hasRuleKey(nextProps.location.query), | |||||
query: parseQuery(nextProps.location.query), | query: parseQuery(nextProps.location.query), | ||||
selected: openRule ? openRule.key : selected | selected: openRule ? openRule.key : selected | ||||
}; | }; | ||||
return false; | return false; | ||||
}); | }); | ||||
key('left', 'coding-rules', () => { | key('left', 'coding-rules', () => { | ||||
this.closeRule(); | |||||
this.handleBack(); | |||||
return false; | return false; | ||||
}); | }); | ||||
}; | }; | ||||
this.makeFetchRequest(query).then(({ actives, facets, paging, rules }) => { | this.makeFetchRequest(query).then(({ actives, facets, paging, rules }) => { | ||||
if (this.mounted) { | if (this.mounted) { | ||||
const openRule = this.getOpenRule(this.props, rules); | const openRule = this.getOpenRule(this.props, rules); | ||||
const usingPermalink = hasRuleKey(this.props.location.query); | |||||
const selected = rules.length > 0 ? (openRule && openRule.key) || rules[0].key : undefined; | const selected = rules.length > 0 ? (openRule && openRule.key) || rules[0].key : undefined; | ||||
this.setState({ actives, facets, loading: false, openRule, paging, rules, selected }); | |||||
this.setState({ | |||||
actives, | |||||
facets, | |||||
loading: false, | |||||
openRule, | |||||
paging, | |||||
rules, | |||||
selected, | |||||
usingPermalink | |||||
}); | |||||
} | } | ||||
}, this.stopLoading); | }, this.stopLoading); | ||||
}; | }; | ||||
this.props.router.push(this.getRulePath(ruleKey)); | this.props.router.push(this.getRulePath(ruleKey)); | ||||
}; | }; | ||||
handleBack = (event: React.SyntheticEvent<HTMLAnchorElement>) => { | |||||
event.preventDefault(); | |||||
event.currentTarget.blur(); | |||||
this.closeRule(); | |||||
handleBack = (event?: React.SyntheticEvent<HTMLAnchorElement>) => { | |||||
const { usingPermalink } = this.state; | |||||
if (event) { | |||||
event.preventDefault(); | |||||
event.currentTarget.blur(); | |||||
} | |||||
if (usingPermalink) { | |||||
this.handleReset(); | |||||
} else { | |||||
this.closeRule(); | |||||
} | |||||
}; | }; | ||||
handleFilterChange = (changes: Partial<Query>) => { | handleFilterChange = (changes: Partial<Query>) => { | ||||
<div className="layout-page-main-inner"> | <div className="layout-page-main-inner"> | ||||
<A11ySkipTarget anchor="rules_main" /> | <A11ySkipTarget anchor="rules_main" /> | ||||
{this.state.openRule ? ( | {this.state.openRule ? ( | ||||
<a className="js-back" href="#" onClick={this.handleBack}> | |||||
{translate('coding_rules.return_to_list')} | |||||
<a | |||||
className="js-back display-inline-flex-center link-no-underline" | |||||
href="#" | |||||
onClick={this.handleBack}> | |||||
<BackIcon className="spacer-right" /> | |||||
{this.state.usingPermalink | |||||
? translate('coding_rules.see_all') | |||||
: translate('coding_rules.return_to_list')} | |||||
</a> | </a> | ||||
) : ( | ) : ( | ||||
this.renderBulkButton() | this.renderBulkButton() | ||||
)} | )} | ||||
<PageActions | |||||
loading={this.state.loading} | |||||
onReload={this.handleReload} | |||||
paging={paging} | |||||
selectedIndex={selectedIndex} | |||||
/> | |||||
{!this.state.usingPermalink && ( | |||||
<PageActions | |||||
loading={this.state.loading} | |||||
onReload={this.handleReload} | |||||
paging={paging} | |||||
selectedIndex={selectedIndex} | |||||
/> | |||||
)} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> |
* along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
*/ | */ | ||||
import * as React from 'react'; | |||||
import { shallow } from 'enzyme'; | import { shallow } from 'enzyme'; | ||||
import * as React from 'react'; | |||||
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; | import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils'; | ||||
import { App } from '../App'; | |||||
import { getRulesApp } from '../../../../api/rules'; | |||||
import ScreenPositionHelper from '../../../../components/common/ScreenPositionHelper'; | |||||
import { isSonarCloud } from '../../../../helpers/system'; | |||||
import { | import { | ||||
mockAppState, | mockAppState, | ||||
mockCurrentUser, | mockCurrentUser, | ||||
mockLocation, | mockLocation, | ||||
mockOrganization, | mockOrganization, | ||||
mockRouter | |||||
mockRouter, | |||||
mockRule | |||||
} from '../../../../helpers/testMocks'; | } from '../../../../helpers/testMocks'; | ||||
import { getRulesApp } from '../../../../api/rules'; | |||||
import { isSonarCloud } from '../../../../helpers/system'; | |||||
import { App } from '../App'; | |||||
jest.mock('../../../../api/rules', () => ({ | |||||
getRulesApp: jest.fn().mockResolvedValue({ canWrite: true, repositories: [] }), | |||||
searchRules: jest.fn().mockResolvedValue({ | |||||
actives: [], | |||||
rawActives: [], | |||||
facets: [], | |||||
rawFacets: [], | |||||
p: 0, | |||||
ps: 100, | |||||
rules: [], | |||||
total: 0 | |||||
}) | |||||
})); | |||||
jest.mock('../../../../components/common/ScreenPositionHelper'); | |||||
jest.mock('../../../../api/rules', () => { | |||||
const { mockRule } = jest.requireActual('../../../../helpers/testMocks'); | |||||
return { | |||||
getRulesApp: jest.fn().mockResolvedValue({ canWrite: true, repositories: [] }), | |||||
searchRules: jest.fn().mockResolvedValue({ | |||||
actives: [], | |||||
rawActives: [], | |||||
facets: [], | |||||
rawFacets: [], | |||||
p: 0, | |||||
ps: 100, | |||||
rules: [mockRule(), mockRule()], | |||||
total: 0 | |||||
}) | |||||
}; | |||||
}); | |||||
jest.mock('../../../../api/quality-profiles', () => ({ | jest.mock('../../../../api/quality-profiles', () => ({ | ||||
searchQualityProfiles: jest.fn().mockResolvedValue({ profiles: [] }) | searchQualityProfiles: jest.fn().mockResolvedValue({ profiles: [] }) | ||||
it('should render correctly', async () => { | it('should render correctly', async () => { | ||||
const wrapper = shallowRender(); | const wrapper = shallowRender(); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
expect(wrapper).toMatchSnapshot('loading'); | |||||
await waitAndUpdate(wrapper); | await waitAndUpdate(wrapper); | ||||
expect(wrapper).toMatchSnapshot(); | |||||
expect(wrapper).toMatchSnapshot('loaded'); | |||||
expect(wrapper.find(ScreenPositionHelper).dive()).toMatchSnapshot( | |||||
'loaded (ScreenPositionHelper)' | |||||
); | |||||
wrapper.setState({ openRule: mockRule() }); | |||||
expect(wrapper).toMatchSnapshot('open rule'); | |||||
expect(wrapper.find(ScreenPositionHelper).dive()).toMatchSnapshot( | |||||
'open rule (ScreenPositionHelper)' | |||||
); | |||||
wrapper.setState({ usingPermalink: true }); | |||||
expect(wrapper).toMatchSnapshot('using permalink'); | |||||
}); | }); | ||||
describe('renderBulkButton', () => { | describe('renderBulkButton', () => { |
/> | /> | ||||
`; | `; | ||||
exports[`should render correctly 1`] = ` | |||||
exports[`should render correctly: loaded (ScreenPositionHelper) 1`] = ` | |||||
<div | |||||
className="layout-page-side" | |||||
style={ | |||||
Object { | |||||
"top": 0, | |||||
} | |||||
} | |||||
> | |||||
<div | |||||
className="layout-page-side-inner" | |||||
> | |||||
<div | |||||
className="layout-page-filters" | |||||
> | |||||
<A11ySkipTarget | |||||
anchor="rules_filters" | |||||
label="coding_rules.skip_to_filters" | |||||
weight={10} | |||||
/> | |||||
<FiltersHeader | |||||
displayReset={false} | |||||
onReset={[Function]} | |||||
/> | |||||
<SearchBox | |||||
className="spacer-bottom" | |||||
id="coding-rules-search" | |||||
minLength={2} | |||||
onChange={[Function]} | |||||
placeholder="search.search_for_rules" | |||||
value="" | |||||
/> | |||||
<FacetsList | |||||
facets={Object {}} | |||||
hideProfileFacet={false} | |||||
onFacetToggle={[Function]} | |||||
onFilterChange={[Function]} | |||||
openFacets={ | |||||
Object { | |||||
"languages": true, | |||||
"owaspTop10": false, | |||||
"sansTop25": false, | |||||
"sonarsourceSecurity": false, | |||||
"standards": false, | |||||
"types": true, | |||||
} | |||||
} | |||||
organization="foo" | |||||
query={ | |||||
Object { | |||||
"activation": undefined, | |||||
"activationSeverities": Array [], | |||||
"availableSince": undefined, | |||||
"compareToProfile": undefined, | |||||
"cwe": Array [], | |||||
"inheritance": undefined, | |||||
"languages": Array [], | |||||
"owaspTop10": Array [], | |||||
"profile": undefined, | |||||
"repositories": Array [], | |||||
"ruleKey": undefined, | |||||
"sansTop25": Array [], | |||||
"searchQuery": undefined, | |||||
"severities": Array [], | |||||
"sonarsourceSecurity": Array [], | |||||
"statuses": Array [], | |||||
"tags": Array [], | |||||
"template": undefined, | |||||
"types": Array [], | |||||
} | |||||
} | |||||
referencedProfiles={Object {}} | |||||
referencedRepositories={Object {}} | |||||
/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
`; | |||||
exports[`should render correctly: loaded 1`] = ` | |||||
<Fragment> | |||||
<Suggestions | |||||
suggestions="coding_rules" | |||||
/> | |||||
<Helmet | |||||
defer={false} | |||||
encodeSpecialCharacters={true} | |||||
title="coding_rules.page" | |||||
> | |||||
<meta | |||||
content="noindex" | |||||
name="robots" | |||||
/> | |||||
</Helmet> | |||||
<div | |||||
className="layout-page" | |||||
id="coding-rules-page" | |||||
> | |||||
<ScreenPositionHelper | |||||
className="layout-page-side-outer" | |||||
> | |||||
<Component /> | |||||
</ScreenPositionHelper> | |||||
<div | |||||
className="layout-page-main" | |||||
> | |||||
<div | |||||
className="layout-page-header-panel layout-page-main-header" | |||||
> | |||||
<div | |||||
className="layout-page-header-panel-inner layout-page-main-header-inner" | |||||
> | |||||
<div | |||||
className="layout-page-main-inner" | |||||
> | |||||
<A11ySkipTarget | |||||
anchor="rules_main" | |||||
/> | |||||
<BulkChange | |||||
languages={ | |||||
Object { | |||||
"js": Object { | |||||
"key": "js", | |||||
"name": "JavaScript", | |||||
}, | |||||
} | |||||
} | |||||
organization="foo" | |||||
query={ | |||||
Object { | |||||
"activation": undefined, | |||||
"activationSeverities": Array [], | |||||
"availableSince": undefined, | |||||
"compareToProfile": undefined, | |||||
"cwe": Array [], | |||||
"inheritance": undefined, | |||||
"languages": Array [], | |||||
"owaspTop10": Array [], | |||||
"profile": undefined, | |||||
"repositories": Array [], | |||||
"ruleKey": undefined, | |||||
"sansTop25": Array [], | |||||
"searchQuery": undefined, | |||||
"severities": Array [], | |||||
"sonarsourceSecurity": Array [], | |||||
"statuses": Array [], | |||||
"tags": Array [], | |||||
"template": undefined, | |||||
"types": Array [], | |||||
} | |||||
} | |||||
referencedProfiles={Object {}} | |||||
total={0} | |||||
/> | |||||
<PageActions | |||||
loading={false} | |||||
onReload={[Function]} | |||||
paging={ | |||||
Object { | |||||
"pageIndex": 0, | |||||
"pageSize": 100, | |||||
"total": 0, | |||||
} | |||||
} | |||||
selectedIndex={0} | |||||
/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div | |||||
className="layout-page-main-inner" | |||||
> | |||||
<RuleListItem | |||||
canWrite={true} | |||||
isLoggedIn={true} | |||||
key="javascript:S1067" | |||||
onActivate={[Function]} | |||||
onDeactivate={[Function]} | |||||
onFilterChange={[Function]} | |||||
onOpen={[Function]} | |||||
organization="foo" | |||||
rule={ | |||||
Object { | |||||
"key": "javascript:S1067", | |||||
"lang": "js", | |||||
"langName": "JavaScript", | |||||
"name": "Use foo", | |||||
"severity": "MAJOR", | |||||
"status": "READY", | |||||
"sysTags": Array [ | |||||
"a", | |||||
"b", | |||||
], | |||||
"tags": Array [ | |||||
"x", | |||||
], | |||||
"type": "CODE_SMELL", | |||||
} | |||||
} | |||||
selected={true} | |||||
/> | |||||
<RuleListItem | |||||
canWrite={true} | |||||
isLoggedIn={true} | |||||
key="javascript:S1067" | |||||
onActivate={[Function]} | |||||
onDeactivate={[Function]} | |||||
onFilterChange={[Function]} | |||||
onOpen={[Function]} | |||||
organization="foo" | |||||
rule={ | |||||
Object { | |||||
"key": "javascript:S1067", | |||||
"lang": "js", | |||||
"langName": "JavaScript", | |||||
"name": "Use foo", | |||||
"severity": "MAJOR", | |||||
"status": "READY", | |||||
"sysTags": Array [ | |||||
"a", | |||||
"b", | |||||
], | |||||
"tags": Array [ | |||||
"x", | |||||
], | |||||
"type": "CODE_SMELL", | |||||
} | |||||
} | |||||
selected={true} | |||||
/> | |||||
<ListFooter | |||||
count={2} | |||||
loadMore={[Function]} | |||||
ready={true} | |||||
total={0} | |||||
/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</Fragment> | |||||
`; | |||||
exports[`should render correctly: loading 1`] = ` | |||||
<Fragment> | <Fragment> | ||||
<Suggestions | <Suggestions | ||||
suggestions="coding_rules" | suggestions="coding_rules" | ||||
</Fragment> | </Fragment> | ||||
`; | `; | ||||
exports[`should render correctly 2`] = ` | |||||
exports[`should render correctly: open rule (ScreenPositionHelper) 1`] = ` | |||||
<div | |||||
className="layout-page-side" | |||||
style={ | |||||
Object { | |||||
"top": 0, | |||||
} | |||||
} | |||||
> | |||||
<div | |||||
className="layout-page-side-inner" | |||||
> | |||||
<div | |||||
className="layout-page-filters" | |||||
> | |||||
<A11ySkipTarget | |||||
anchor="rules_filters" | |||||
label="coding_rules.skip_to_filters" | |||||
weight={10} | |||||
/> | |||||
<FiltersHeader | |||||
displayReset={false} | |||||
onReset={[Function]} | |||||
/> | |||||
<SearchBox | |||||
className="spacer-bottom" | |||||
id="coding-rules-search" | |||||
minLength={2} | |||||
onChange={[Function]} | |||||
placeholder="search.search_for_rules" | |||||
value="" | |||||
/> | |||||
<FacetsList | |||||
facets={Object {}} | |||||
hideProfileFacet={false} | |||||
onFacetToggle={[Function]} | |||||
onFilterChange={[Function]} | |||||
openFacets={ | |||||
Object { | |||||
"languages": true, | |||||
"owaspTop10": false, | |||||
"sansTop25": false, | |||||
"sonarsourceSecurity": false, | |||||
"standards": false, | |||||
"types": true, | |||||
} | |||||
} | |||||
organization="foo" | |||||
query={ | |||||
Object { | |||||
"activation": undefined, | |||||
"activationSeverities": Array [], | |||||
"availableSince": undefined, | |||||
"compareToProfile": undefined, | |||||
"cwe": Array [], | |||||
"inheritance": undefined, | |||||
"languages": Array [], | |||||
"owaspTop10": Array [], | |||||
"profile": undefined, | |||||
"repositories": Array [], | |||||
"ruleKey": undefined, | |||||
"sansTop25": Array [], | |||||
"searchQuery": undefined, | |||||
"severities": Array [], | |||||
"sonarsourceSecurity": Array [], | |||||
"statuses": Array [], | |||||
"tags": Array [], | |||||
"template": undefined, | |||||
"types": Array [], | |||||
} | |||||
} | |||||
referencedProfiles={Object {}} | |||||
referencedRepositories={Object {}} | |||||
/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
`; | |||||
exports[`should render correctly: open rule 1`] = ` | |||||
<Fragment> | <Fragment> | ||||
<Suggestions | <Suggestions | ||||
suggestions="coding_rules" | suggestions="coding_rules" | ||||
<A11ySkipTarget | <A11ySkipTarget | ||||
anchor="rules_main" | anchor="rules_main" | ||||
/> | /> | ||||
<BulkChange | |||||
languages={ | |||||
Object { | |||||
"js": Object { | |||||
"key": "js", | |||||
"name": "JavaScript", | |||||
}, | |||||
} | |||||
} | |||||
organization="foo" | |||||
query={ | |||||
Object { | |||||
"activation": undefined, | |||||
"activationSeverities": Array [], | |||||
"availableSince": undefined, | |||||
"compareToProfile": undefined, | |||||
"cwe": Array [], | |||||
"inheritance": undefined, | |||||
"languages": Array [], | |||||
"owaspTop10": Array [], | |||||
"profile": undefined, | |||||
"repositories": Array [], | |||||
"ruleKey": undefined, | |||||
"sansTop25": Array [], | |||||
"searchQuery": undefined, | |||||
"severities": Array [], | |||||
"sonarsourceSecurity": Array [], | |||||
"statuses": Array [], | |||||
"tags": Array [], | |||||
"template": undefined, | |||||
"types": Array [], | |||||
} | |||||
} | |||||
referencedProfiles={Object {}} | |||||
total={0} | |||||
/> | |||||
<a | |||||
className="js-back display-inline-flex-center link-no-underline" | |||||
href="#" | |||||
onClick={[Function]} | |||||
> | |||||
<BackIcon | |||||
className="spacer-right" | |||||
/> | |||||
coding_rules.return_to_list | |||||
</a> | |||||
<PageActions | <PageActions | ||||
loading={false} | loading={false} | ||||
onReload={[Function]} | onReload={[Function]} | ||||
"total": 0, | "total": 0, | ||||
} | } | ||||
} | } | ||||
selectedIndex={0} | |||||
/> | /> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div | <div | ||||
className="layout-page-main-inner" | className="layout-page-main-inner" | ||||
> | > | ||||
<ListFooter | |||||
count={0} | |||||
loadMore={[Function]} | |||||
ready={true} | |||||
total={0} | |||||
<RuleDetails | |||||
allowCustomRules={true} | |||||
canWrite={true} | |||||
hideQualityProfiles={false} | |||||
onActivate={[Function]} | |||||
onDeactivate={[Function]} | |||||
onDelete={[Function]} | |||||
onFilterChange={[Function]} | |||||
organization="foo" | |||||
referencedProfiles={Object {}} | |||||
referencedRepositories={Object {}} | |||||
ruleKey="javascript:S1067" | |||||
/> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</Fragment> | |||||
`; | |||||
exports[`should render correctly: using permalink 1`] = ` | |||||
<Fragment> | |||||
<Suggestions | |||||
suggestions="coding_rules" | |||||
/> | |||||
<Helmet | |||||
defer={false} | |||||
encodeSpecialCharacters={true} | |||||
title="coding_rules.page" | |||||
> | |||||
<meta | |||||
content="noindex" | |||||
name="robots" | |||||
/> | |||||
</Helmet> | |||||
<div | |||||
className="layout-page" | |||||
id="coding-rules-page" | |||||
> | |||||
<ScreenPositionHelper | |||||
className="layout-page-side-outer" | |||||
> | |||||
<Component /> | |||||
</ScreenPositionHelper> | |||||
<div | |||||
className="layout-page-main" | |||||
> | |||||
<div | |||||
className="layout-page-header-panel layout-page-main-header" | |||||
> | |||||
<div | |||||
className="layout-page-header-panel-inner layout-page-main-header-inner" | |||||
> | |||||
<div | |||||
className="layout-page-main-inner" | |||||
> | |||||
<A11ySkipTarget | |||||
anchor="rules_main" | |||||
/> | |||||
<a | |||||
className="js-back display-inline-flex-center link-no-underline" | |||||
href="#" | |||||
onClick={[Function]} | |||||
> | |||||
<BackIcon | |||||
className="spacer-right" | |||||
/> | |||||
coding_rules.see_all | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div | |||||
className="layout-page-main-inner" | |||||
> | |||||
<RuleDetails | |||||
allowCustomRules={true} | |||||
canWrite={true} | |||||
hideQualityProfiles={false} | |||||
onActivate={[Function]} | |||||
onDeactivate={[Function]} | |||||
onDelete={[Function]} | |||||
onFilterChange={[Function]} | |||||
organization="foo" | |||||
referencedProfiles={Object {}} | |||||
referencedRepositories={Object {}} | |||||
ruleKey="javascript:S1067" | |||||
/> | /> | ||||
</div> | </div> | ||||
</div> | </div> |
return query.open; | return query.open; | ||||
} | } | ||||
export function hasRuleKey(query: T.RawQuery) { | |||||
return Boolean(query.rule_key); | |||||
} | |||||
function parseAsInheritance(value?: string): T.RuleInheritance | undefined { | function parseAsInheritance(value?: string): T.RuleInheritance | undefined { | ||||
if (value === 'INHERITED' || value === 'NONE' || value === 'OVERRIDES') { | if (value === 'INHERITED' || value === 'NONE' || value === 'OVERRIDES') { | ||||
return value; | return value; |
import getPages from '../../pages'; | import getPages from '../../pages'; | ||||
import App from '../App'; | import App from '../App'; | ||||
jest.mock('../../../../components/common/ScreenPositionHelper', () => ({ | |||||
default: class ScreenPositionHelper extends React.Component<{ | |||||
children: (pos: { top: number }) => React.ReactNode; | |||||
}> { | |||||
static displayName = 'ScreenPositionHelper'; | |||||
render() { | |||||
return this.props.children({ top: 0 }); | |||||
} | |||||
} | |||||
})); | |||||
jest.mock('../../../../components/common/ScreenPositionHelper'); | |||||
jest.mock('../../../../helpers/system', () => ({ | jest.mock('../../../../helpers/system', () => ({ | ||||
isSonarCloud: jest.fn().mockReturnValue(false) | isSonarCloud: jest.fn().mockReturnValue(false) |
import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; | import { mockLocation, mockRouter } from '../../../../helpers/testMocks'; | ||||
import { WebApiApp } from '../WebApiApp'; | import { WebApiApp } from '../WebApiApp'; | ||||
jest.mock('../../../../components/common/ScreenPositionHelper'); | |||||
jest.mock('../../../../api/web-api', () => ({ | jest.mock('../../../../api/web-api', () => ({ | ||||
fetchWebApi: jest.fn().mockResolvedValue([ | fetchWebApi: jest.fn().mockResolvedValue([ | ||||
{ | { | ||||
removeSideBarClass: jest.fn() | removeSideBarClass: jest.fn() | ||||
})); | })); | ||||
jest.mock('../../../../components/common/ScreenPositionHelper', () => ({ | |||||
default: class ScreenPositionHelper extends React.Component<{ | |||||
children: (pos: { top: number }) => React.ReactNode; | |||||
}> { | |||||
static displayName = 'ScreenPositionHelper'; | |||||
render() { | |||||
return this.props.children({ top: 0 }); | |||||
} | |||||
} | |||||
})); | |||||
it('should render correctly', async () => { | it('should render correctly', async () => { | ||||
(global as any).scrollTo = jest.fn(); | (global as any).scrollTo = jest.fn(); | ||||
/* | |||||
* SonarQube | |||||
* Copyright (C) 2009-2020 SonarSource SA | |||||
* mailto:info AT sonarsource DOT com | |||||
* | |||||
* This program is free software; you can redistribute it and/or | |||||
* modify it under the terms of the GNU Lesser General Public | |||||
* License as published by the Free Software Foundation; either | |||||
* version 3 of the License, or (at your option) any later version. | |||||
* | |||||
* This program is distributed in the hope that it will be useful, | |||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||||
* Lesser General Public License for more details. | |||||
* | |||||
* You should have received a copy of the GNU Lesser General Public License | |||||
* along with this program; if not, write to the Free Software Foundation, | |||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||||
*/ | |||||
import * as React from 'react'; | |||||
interface Props { | |||||
children: (position: { top: number }) => React.ReactNode; | |||||
} | |||||
export default class ScreenPositionHelper extends React.Component<Props> { | |||||
render() { | |||||
return this.props.children({ top: 0 }); | |||||
} | |||||
} |
coding_rules.quality_profile=Quality Profile | coding_rules.quality_profile=Quality Profile | ||||
coding_rules.reactivate=Reactivate | coding_rules.reactivate=Reactivate | ||||
coding_rules.reactivate.help=A rule with the same key has been previously deleted. Please reactivate the existing rule or modify the key to create a new rule. | coding_rules.reactivate.help=A rule with the same key has been previously deleted. Please reactivate the existing rule or modify the key to create a new rule. | ||||
coding_rules.return_to_list=Return to List | |||||
coding_rules.return_to_list=Return to list | |||||
coding_rules.see_all=See all rules | |||||
coding_rules.remove_extended_description=Remove Extended Description | coding_rules.remove_extended_description=Remove Extended Description | ||||
coding_rules.remove_extended_description.confirm=Are you sure you want to remove the extended description? | coding_rules.remove_extended_description.confirm=Are you sure you want to remove the extended description? | ||||
coding_rules.repository_language=Rule repository (language) | coding_rules.repository_language=Rule repository (language) |