浏览代码

SONAR-14309 Update eslint, typescript and fix issues

tags/8.7.0.41497
Jeremy Davis 3 年前
父节点
当前提交
d6b1b8a262
共有 80 个文件被更改,包括 1681 次插入710 次删除
  1. 10
    9
      server/sonar-docs/package.json
  2. 6
    1
      server/sonar-docs/src/__tests__/BrokenLinkSafetyNet.test.js
  3. 1
    1
      server/sonar-docs/src/components/__tests__/Sidebar-test.tsx
  4. 678
    70
      server/sonar-docs/yarn.lock
  5. 10
    10
      server/sonar-web/package.json
  6. 1
    1
      server/sonar-web/src/main/js/app/components/App.tsx
  7. 1
    1
      server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
  8. 24
    1
      server/sonar-web/src/main/js/app/components/extensions/legacy/__tests__/request-legacy-test.ts
  9. 7
    2
      server/sonar-web/src/main/js/app/components/extensions/legacy/request-legacy.ts
  10. 10
    4
      server/sonar-web/src/main/js/app/components/indexation/__tests__/PageUnavailableDueToIndexation-test.tsx
  11. 4
    2
      server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx
  12. 0
    1
      server/sonar-web/src/main/js/app/components/nav/component/__tests__/Menu-test.tsx
  13. 1
    1
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts
  14. 1
    1
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/meta/__tests__/MetaTagsSelector-test.tsx
  15. 0
    1
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx
  16. 1
    1
      server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx
  17. 2
    1
      server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx
  18. 6
    3
      server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx
  19. 8
    4
      server/sonar-web/src/main/js/app/index.ts
  20. 1
    1
      server/sonar-web/src/main/js/apps/application-console/__tests__/EditForm-test.tsx
  21. 1
    1
      server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/RuleDetails-test.tsx
  22. 1
    1
      server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureContent-test.tsx
  23. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/AzureProjectCreate-test.tsx
  24. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/AzureProjectCreateRenderer-test.tsx
  25. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx
  26. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx
  27. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx
  28. 1
    1
      server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx
  29. 1
    1
      server/sonar-web/src/main/js/apps/documentation/__tests__/pages-test.ts
  30. 2
    2
      server/sonar-web/src/main/js/apps/documentation/components/__tests__/App-test.tsx
  31. 2
    1
      server/sonar-web/src/main/js/apps/groups/components/App.tsx
  32. 0
    1
      server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx
  33. 0
    1
      server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.tsx
  34. 1
    3
      server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx
  35. 0
    1
      server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap
  36. 1
    1
      server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx
  37. 1
    1
      server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx
  38. 8
    8
      server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx
  39. 1
    1
      server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx
  40. 1
    1
      server/sonar-web/src/main/js/apps/portfolio/components/__tests__/MetricBox-test.tsx
  41. 1
    1
      server/sonar-web/src/main/js/apps/portfolio/components/__tests__/Report-test.tsx
  42. 1
    1
      server/sonar-web/src/main/js/apps/portfolio/components/__tests__/Subscription-test.tsx
  43. 1
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.tsx
  44. 1
    1
      server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysis-test.tsx
  45. 1
    1
      server/sonar-web/src/main/js/apps/projectBaseline/components/__tests__/BranchAnalysisListRenderer-test.tsx
  46. 13
    14
      server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx
  47. 6
    5
      server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/ProjectQualityGateAppRenderer-test.tsx
  48. 31
    33
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx
  49. 30
    35
      server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx
  50. 1
    1
      server/sonar-web/src/main/js/apps/projects/components/__tests__/AllProjects-test.tsx
  51. 48
    51
      server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx
  52. 1
    3
      server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-test.tsx
  53. 1
    1
      server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfilePermissionsFormSelect-test.tsx
  54. 4
    4
      server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotOpenInIdeButton-test.tsx.snap
  55. 1
    1
      server/sonar-web/src/main/js/apps/settings/components/__tests__/EmailForm-test.tsx
  56. 1
    1
      server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts
  57. 5
    6
      server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx
  58. 7
    0
      server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerBase-test.tsx
  59. 1
    1
      server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineSCM-test.tsx
  60. 1
    1
      server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/SCMPopup-test.tsx
  61. 1
    1
      server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsHistory-test.tsx
  62. 1
    1
      server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsTooltips-test.tsx
  63. 1
    1
      server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsTooltipsContentCoverage-test.tsx
  64. 1
    1
      server/sonar-web/src/main/js/components/activity-graph/__tests__/utils-test.ts
  65. 7
    3
      server/sonar-web/src/main/js/components/common/BranchStatus.tsx
  66. 17
    22
      server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx
  67. 1
    2
      server/sonar-web/src/main/js/components/common/__tests__/BranchStatus-test.tsx
  68. 1
    0
      server/sonar-web/src/main/js/components/docs/DocCollapsibleBlock.tsx
  69. 3
    3
      server/sonar-web/src/main/js/components/docs/__tests__/DocToc-test.tsx
  70. 2
    0
      server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocCollapsibleBlock-test.tsx.snap
  71. 1
    1
      server/sonar-web/src/main/js/components/measure/__tests__/Measure-test.tsx
  72. 1
    0
      server/sonar-web/src/main/js/components/tutorials/components/RenderOptions.tsx
  73. 3
    3
      server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/RenderOptions-test.tsx.snap
  74. 1
    1
      server/sonar-web/src/main/js/helpers/extensions.ts
  75. 1
    1
      server/sonar-web/src/main/js/helpers/mocks/quality-gates.ts
  76. 1
    1
      server/sonar-web/src/main/js/helpers/testMocks.ts
  77. 2
    4
      server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx
  78. 1
    1
      server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx
  79. 1
    1
      server/sonar-web/src/main/js/store/__tests__/users-test.tsx
  80. 680
    355
      server/sonar-web/yarn.lock

+ 10
- 9
server/sonar-docs/package.json 查看文件

@@ -36,19 +36,20 @@
"@types/react-dom": "16.8.4",
"@types/react-helmet": "5.0.15",
"@types/rehype-react": "4.0.0",
"@typescript-eslint/parser": "2.6.0",
"@typescript-eslint/eslint-plugin": "4.13.0",
"@typescript-eslint/parser": "4.13.0",
"babel-jest": "25.1.0",
"enzyme": "3.11.0",
"enzyme-adapter-react-16": "1.15.2",
"enzyme-to-json": "3.4.4",
"eslint": "6.8.0",
"eslint-config-sonarqube": "0.6.1",
"eslint-plugin-import": "2.20.1",
"eslint-plugin-jest": "23.8.2",
"eslint-plugin-jsx-a11y": "6.2.3",
"eslint": "7.17.0",
"eslint-config-sonarqube": "1.0.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jest": "24.1.0",
"eslint-plugin-jsx-a11y": "6.4.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-react": "7.19.0",
"eslint-plugin-react-hooks": "2.5.0",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"eslint-plugin-sonarjs": "0.5.0",
"fs-extra": "7.0.1",
"glob-promise": "3.4.0",
@@ -59,7 +60,7 @@
"react-test-renderer": "16.8.5",
"remark": "11.0.2",
"ts-jest": "25.2.1",
"typescript": "3.8.3",
"typescript": "4.1.3",
"unist-util-visit": "2.0.2"
},
"scripts": {

+ 6
- 1
server/sonar-docs/src/__tests__/BrokenLinkSafetyNet.test.js 查看文件

@@ -87,7 +87,7 @@ it('should have valid links in suggestions file', () => {
expect(hasErrors).toBe(false);
});

it('should have valid and uniq links in url metadata field', () => {
function collectErrors() {
let urlLists = [];
let hasErrors = false;
parsedFiles.forEach(file => {
@@ -103,6 +103,11 @@ it('should have valid and uniq links in url metadata field', () => {

urlLists = [...urlLists, file.frontmatter.url];
});
return hasErrors;
}

it('should have valid and uniq links in url metadata field', () => {
const hasErrors = collectErrors();
expect(hasErrors).toBe(false);
});


+ 1
- 1
server/sonar-docs/src/components/__tests__/Sidebar-test.tsx 查看文件

@@ -25,7 +25,7 @@ import Sidebar from '../Sidebar';

jest.mock('../navTreeUtils', () => {
return {
...require.requireActual('../navTreeUtils'),
...jest.requireActual('../navTreeUtils'),
getNavTree: jest.fn().mockReturnValue([
'/foo/',
{

+ 678
- 70
server/sonar-docs/yarn.lock
文件差异内容过多而无法显示
查看文件


+ 10
- 10
server/sonar-web/package.json 查看文件

@@ -70,7 +70,8 @@
"@types/react-virtualized": "9.21.8",
"@types/sanitize-html": "1.22.0",
"@types/valid-url": "1.0.2",
"@typescript-eslint/parser": "2.24.0",
"@typescript-eslint/eslint-plugin": "4.13.0",
"@typescript-eslint/parser": "4.13.0",
"autoprefixer": "9.7.4",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "25.1.0",
@@ -86,15 +87,14 @@
"enzyme-adapter-react-16": "1.15.2",
"enzyme-to-json": "3.4.4",
"escape-string-regexp": "2.0.0",
"eslint": "6.8.0",
"eslint-config-sonarqube": "0.6.1",
"eslint-plugin-import": "2.20.1",
"eslint-plugin-jest": "23.8.2",
"eslint-plugin-jsx-a11y": "6.2.3",
"eslint": "7.17.0",
"eslint-config-sonarqube": "1.0.0",
"eslint-plugin-import": "2.22.0",
"eslint-plugin-jest": "24.1.0",
"eslint-plugin-jsx-a11y": "6.4.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-react": "7.19.0",
"eslint-plugin-react-hooks": "2.5.0",
"eslint-plugin-sonarjs": "0.5.0",
"eslint-plugin-react": "7.22.0",
"eslint-plugin-react-hooks": "4.2.0",
"expose-loader": "0.7.5",
"glob": "7.1.6",
"glob-promise": "3.4.0",
@@ -116,7 +116,7 @@
"style-loader": "1.1.3",
"ts-jest": "25.2.1",
"ts-loader": "6.2.1",
"typescript": "3.8.3",
"typescript": "4.1.3",
"webpack": "4.42.0",
"webpack-bundle-analyzer": "3.6.1",
"webpack-dev-server": "3.10.3"

+ 1
- 1
server/sonar-web/src/main/js/app/components/App.tsx 查看文件

@@ -61,7 +61,7 @@ class App extends React.PureComponent<Props> {
const outer = document.createElement('div');
outer.style.visibility = 'hidden';
outer.style.width = '100px';
outer.style.msOverflowStyle = 'scrollbar';
outer.style.setProperty('msOverflowStyle', 'scrollbar');

document.body.appendChild(outer);


+ 1
- 1
server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx 查看文件

@@ -33,7 +33,7 @@ import { ComponentContainer } from '../ComponentContainer';
import PageUnavailableDueToIndexation from '../indexation/PageUnavailableDueToIndexation';

jest.mock('../../../api/branches', () => {
const { mockMainBranch, mockPullRequest } = require.requireActual(
const { mockMainBranch, mockPullRequest } = jest.requireActual(
'../../../helpers/mocks/branch-like'
);
return {

+ 24
- 1
server/sonar-web/src/main/js/app/components/extensions/legacy/__tests__/request-legacy-test.ts 查看文件

@@ -20,13 +20,21 @@
import handleRequiredAuthentication from 'sonar-ui-common/helpers/handleRequiredAuthentication';
import request from '../request-legacy';

const { checkStatus, parseError, requestTryAndRepeatUntil } = request;
const { checkStatus, delay, parseError, requestTryAndRepeatUntil } = request;

jest.mock('sonar-ui-common/helpers/handleRequiredAuthentication', () => ({ default: jest.fn() }));
jest.mock('sonar-ui-common/helpers/cookies', () => ({
getCookie: jest.fn().mockReturnValue('qwerasdf')
}));

beforeAll(() => {
jest.useFakeTimers();
});

afterAll(() => {
jest.useRealTimers();
});

beforeEach(() => {
jest.clearAllMocks();
});
@@ -91,6 +99,7 @@ describe('requestTryAndRepeatUntil', () => {
for (let i = 1; i < 5; i++) {
jest.runAllTimers();
expect(apiCall).toBeCalledTimes(i);
// eslint-disable-next-line no-await-in-loop
await new Promise(setImmediate);
expect(stopRepeat).toBeCalledTimes(i);
}
@@ -115,6 +124,7 @@ describe('requestTryAndRepeatUntil', () => {
for (let i = 1; i < 5; i++) {
jest.runAllTimers();
expect(apiCall).toBeCalledTimes(i);
// eslint-disable-next-line no-await-in-loop
await new Promise(setImmediate);
}
apiCall.mockResolvedValue('Success');
@@ -141,6 +151,7 @@ describe('requestTryAndRepeatUntil', () => {
for (let i = 1; i < 3; i++) {
jest.runAllTimers();
expect(apiCall).toBeCalledTimes(i);
// eslint-disable-next-line no-await-in-loop
await new Promise(setImmediate);
}
apiCall.mockResolvedValue('Success');
@@ -156,6 +167,7 @@ describe('requestTryAndRepeatUntil', () => {
for (let i = 1; i < 3; i++) {
jest.advanceTimersByTime(500);
expect(apiCall).toBeCalledTimes(i);
// eslint-disable-next-line no-await-in-loop
await new Promise(setImmediate);
}

@@ -284,3 +296,14 @@ describe('request functions', () => {
});
});
});

describe('delay', () => {
it('should work as expected', async () => {
const param = { some: 'response' };

const promise = delay(param);
jest.runAllTimers();

expect(await promise).toBe(param);
});
});

+ 7
- 2
server/sonar-web/src/main/js/app/components/extensions/legacy/request-legacy.ts 查看文件

@@ -87,7 +87,10 @@ const DEFAULT_HEADERS = {
class Request {
private data?: RequestData;

constructor(private readonly url: string, private readonly options: { method?: string } = {}) {}
constructor(private readonly url: string, private readonly options: { method?: string } = {}) {
this.url = url;
this.options = options;
}

getSubmitData(customHeaders: any = {}): { url: string; options: RequestInit } {
let { url } = this;
@@ -257,7 +260,9 @@ function requestDelete(url: string, data?: RequestData): Promise<any> {
* Delay promise for testing purposes
*/
function delay(response: any): Promise<any> {
return new Promise(resolve => setTimeout(() => resolve(response), 1200));
return new Promise(resolve => {
setTimeout(() => resolve(response), 1200);
});
}

function tryRequestAgain<T>(

+ 10
- 4
server/sonar-web/src/main/js/app/components/indexation/__tests__/PageUnavailableDueToIndexation-test.tsx 查看文件

@@ -29,8 +29,11 @@ it('should render correctly', () => {

it('should not refresh the page once the indexation is complete if there were failures', () => {
const reload = jest.fn();
delete window.location;
(window as any).location = { reload };

Object.defineProperty(window, 'location', {
writable: true,
value: { reload }
});

const wrapper = shallowRender();

@@ -46,8 +49,11 @@ it('should not refresh the page once the indexation is complete if there were fa

it('should refresh the page once the indexation is complete if there were NO failures', () => {
const reload = jest.fn();
delete window.location;
(window as any).location = { reload };

Object.defineProperty(window, 'location', {
writable: true,
value: { reload }
});

const wrapper = shallowRender();


+ 4
- 2
server/sonar-web/src/main/js/app/components/nav/component/Menu.tsx 查看文件

@@ -266,7 +266,8 @@ export class Menu extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', { active: isSettingsActive || open })}
href="#"
id="component-navigation-admin"
@@ -558,7 +559,8 @@ export class Menu extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', { active: open })}
href="#"
id="component-navigation-more"

+ 0
- 1
server/sonar-web/src/main/js/app/components/nav/component/__tests__/Menu-test.tsx 查看文件

@@ -17,7 +17,6 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import {

+ 1
- 1
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/badges/__tests__/utils-test.ts 查看文件

@@ -21,7 +21,7 @@ import { Location } from 'sonar-ui-common/helpers/urls';
import { BadgeOptions, BadgeType, getBadgeSnippet, getBadgeUrl } from '../utils';

jest.mock('sonar-ui-common/helpers/urls', () => ({
...require.requireActual('sonar-ui-common/helpers/urls'),
...jest.requireActual('sonar-ui-common/helpers/urls'),
getHostUrl: () => 'host',
getPathUrlAsString: (o: Location) =>
`host${o.pathname}?id=${o.query ? o.query.id : ''}&branch=${o.query ? o.query.branch : ''}`

+ 1
- 1
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/meta/__tests__/MetaTagsSelector-test.tsx 查看文件

@@ -28,7 +28,7 @@ jest.mock('../../../../../../../api/components', () => ({
}));

jest.mock('lodash', () => {
const lodash = require.requireActual('lodash');
const lodash = jest.requireActual('lodash');
lodash.debounce = jest.fn(fn => fn);
return lodash;
});

+ 0
- 1
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/ProjectNotifications.tsx 查看文件

@@ -28,7 +28,6 @@ import {
} from '../../../../../../components/hoc/withNotifications';

interface Props {
className?: string;
component: T.Component;
}


+ 1
- 1
server/sonar-web/src/main/js/app/components/nav/component/projectInformation/notifications/__tests__/ProjectNotifications-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockComponent } from '../../../../../../../helpers/testMocks';

+ 2
- 1
server/sonar-web/src/main/js/app/components/nav/global/GlobalNavMenu.tsx 查看文件

@@ -139,7 +139,8 @@ export default class GlobalNavMenu extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', { active: open })}
href="#"
id="global-navigation-more"

+ 6
- 3
server/sonar-web/src/main/js/app/components/nav/settings/SettingsNav.tsx 查看文件

@@ -120,7 +120,8 @@ export default class SettingsNav extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', {
active:
open ||
@@ -162,7 +163,8 @@ export default class SettingsNav extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', { active: open || this.isProjectsActive() })}
href="#"
onClick={onToggleClick}>
@@ -205,7 +207,8 @@ export default class SettingsNav extends React.PureComponent<Props> {
{({ onToggleClick, open }) => (
<a
aria-expanded={open}
aria-haspopup="true"
aria-haspopup="menu"
role="button"
className={classNames('dropdown-toggle', { active: open || this.isSecurityActive() })}
href="#"
onClick={onToggleClick}>

+ 8
- 4
server/sonar-web/src/main/js/app/index.ts 查看文件

@@ -46,11 +46,15 @@ if (isMainApp()) {
} else {
// login, maintenance or setup pages

const appStatePromise: Promise<T.AppState> = new Promise(resolve =>
const appStatePromise: Promise<T.AppState | undefined> = new Promise(resolve => {
loadAppState()
.then(data => resolve(data))
.catch(() => resolve(undefined))
);
.then(data => {
resolve(data);
})
.catch(() => {
resolve(undefined);
});
});

Promise.all([loadL10nBundle(), appStatePromise, loadApp()]).then(
([l10nBundle, appState, startReactApp]) => {

+ 1
- 1
server/sonar-web/src/main/js/apps/application-console/__tests__/EditForm-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import SimpleModal from 'sonar-ui-common/components/controls/SimpleModal';

+ 1
- 1
server/sonar-web/src/main/js/apps/coding-rules/components/__tests__/RuleDetails-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';

+ 1
- 1
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/MeasureContent-test.tsx 查看文件

@@ -25,7 +25,7 @@ import { mockComponentMeasure, mockRouter } from '../../../../helpers/testMocks'
import MeasureContent from '../MeasureContent';

jest.mock('../../../../api/components', () => {
const { mockComponentMeasure } = require.requireActual('../../../../helpers/testMocks');
const { mockComponentMeasure } = jest.requireActual('../../../../helpers/testMocks');
return {
getComponentTree: jest.fn().mockResolvedValue({
paging: { pageIndex: 1, pageSize: 500, total: 2 },

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/AzureProjectCreate-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/AzureProjectCreateRenderer-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockAzureProject, mockAzureRepository } from '../../../../helpers/mocks/alm-integrations';

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketImportRepositoryForm-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import SearchBox from 'sonar-ui-common/components/controls/SearchBox';

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketProjectAccordion-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import Radio from 'sonar-ui-common/components/controls/Radio';

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketRepositories-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { click } from 'sonar-ui-common/helpers/testUtils';

+ 1
- 1
server/sonar-web/src/main/js/apps/create/project/__tests__/ManualProjectCreate-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { SubmitButton } from 'sonar-ui-common/components/controls/buttons';

+ 1
- 1
server/sonar-web/src/main/js/apps/documentation/__tests__/pages-test.ts 查看文件

@@ -123,5 +123,5 @@ it('should not break the whole doc when one page cannot be parsed', () => {
function getPages(overrides: T.Dict<ParsedContent> = {}) {
// This allows the use of out-of-scope data inside jest.mock
// Usually, it is impossible as jest.mock'ed module is hoisted on the top of the file
return require.requireActual('../pages').default(overrides);
return jest.requireActual('../pages').default(overrides);
}

+ 2
- 2
server/sonar-web/src/main/js/apps/documentation/components/__tests__/App-test.tsx 查看文件

@@ -84,7 +84,7 @@ jest.mock('sonar-ui-common/helpers/pages', () => ({
}));

jest.mock('sonar-ui-common/helpers/request', () => {
const { mockDocumentationMarkdown } = require.requireActual('../../../../helpers/testMocks');
const { mockDocumentationMarkdown } = jest.requireActual('../../../../helpers/testMocks');
return {
request: jest.fn(() => ({
submit: jest.fn().mockResolvedValue({
@@ -96,7 +96,7 @@ jest.mock('sonar-ui-common/helpers/request', () => {
});

jest.mock('../../pages', () => {
const { mockDocumentationEntry } = require.requireActual('../../../../helpers/testMocks');
const { mockDocumentationEntry } = jest.requireActual('../../../../helpers/testMocks');
return {
default: jest
.fn()

+ 2
- 1
server/sonar-web/src/main/js/apps/groups/components/App.tsx 查看文件

@@ -110,7 +110,8 @@ export default class App extends React.PureComponent<{}, State> {
// reload all pages in order
if (paging && paging.pageIndex > 1) {
for (let p = 1; p < paging.pageIndex; p++) {
await this.fetchMoreGroups();
// eslint-disable-next-line no-await-in-loop
await this.fetchMoreGroups(); // This is a intentional promise chain
}
}
};

+ 0
- 1
server/sonar-web/src/main/js/apps/issues/components/ComponentBreadcrumbs.tsx 查看文件

@@ -25,7 +25,6 @@ import { getSelectedLocation } from '../utils';
interface Props {
component?: T.Component;
issue: T.Issue;
link?: boolean;
selectedFlowIndex?: number;
selectedLocationIndex?: number;
}

+ 0
- 1
server/sonar-web/src/main/js/apps/issues/components/IssuesCounter.tsx 查看文件

@@ -22,7 +22,6 @@ import { translate } from 'sonar-ui-common/helpers/l10n';
import PageCounter from '../../../components/common/PageCounter';

interface Props {
className?: string;
current: number | undefined;
total: number;
}

+ 1
- 3
server/sonar-web/src/main/js/apps/issues/components/PageActions.tsx 查看文件

@@ -61,9 +61,7 @@ export default class PageActions extends React.PureComponent<Props> {

<div className="issues-page-actions">
<ReloadButton onClick={this.props.onReload} />
{paging != null && (
<IssuesCounter className="spacer-left" current={selectedIndex} total={paging.total} />
)}
{paging != null && <IssuesCounter current={selectedIndex} total={paging.total} />}
{effortTotal !== undefined && <TotalEffort effort={effortTotal} />}
</div>


+ 0
- 1
server/sonar-web/src/main/js/apps/issues/components/__tests__/__snapshots__/PageActions-test.tsx.snap 查看文件

@@ -43,7 +43,6 @@ exports[`should render 1`] = `
onClick={[MockFunction]}
/>
<IssuesCounter
className="spacer-left"
current={5}
total={12345}
/>

+ 1
- 1
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/__tests__/CrossComponentSourceViewerWrapper-test.tsx 查看文件

@@ -32,7 +32,7 @@ import {
import CrossComponentSourceViewerWrapper from '../CrossComponentSourceViewerWrapper';

jest.mock('../../../../api/issues', () => {
const { mockSnippetsByComponent } = require.requireActual('../../../../helpers/testMocks');
const { mockSnippetsByComponent } = jest.requireActual('../../../../helpers/testMocks');
return {
getIssueFlowSnippets: jest.fn().mockResolvedValue({ 'main.js': mockSnippetsByComponent() })
};

+ 1
- 1
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/StandardFacet-test.tsx 查看文件

@@ -25,7 +25,7 @@ import { Query } from '../../utils';
import StandardFacet from '../StandardFacet';

jest.mock('../../../../helpers/security-standard', () => ({
...require.requireActual('../../../../helpers/security-standard'),
...jest.requireActual('../../../../helpers/security-standard'),
getStandards: jest.fn().mockResolvedValue({
owaspTop10: {
a1: {

+ 8
- 8
server/sonar-web/src/main/js/apps/overview/branches/__tests__/BranchOverview-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { isDiffMetric } from 'sonar-ui-common/helpers/measures';
@@ -45,7 +45,7 @@ jest.mock('sonar-ui-common/helpers/dates', () => ({
}));

jest.mock('../../../../api/measures', () => {
const { mockMeasure, mockMetric } = require.requireActual('../../../../helpers/testMocks');
const { mockMeasure, mockMetric } = jest.requireActual('../../../../helpers/testMocks');
return {
getMeasuresWithPeriodAndMetrics: jest.fn((_, metricKeys: string[]) => {
const metrics: T.Metric[] = [];
@@ -83,10 +83,10 @@ jest.mock('../../../../api/measures', () => {
});

jest.mock('../../../../api/quality-gates', () => {
const { mockQualityGateProjectStatus, mockQualityGateApplicationStatus } = require.requireActual(
const { mockQualityGateProjectStatus, mockQualityGateApplicationStatus } = jest.requireActual(
'../../../../helpers/mocks/quality-gates'
);
const { MetricKey } = require.requireActual('../../../../types/metrics');
const { MetricKey } = jest.requireActual('../../../../types/metrics');
return {
getQualityGateProjectStatus: jest.fn().mockResolvedValue(
mockQualityGateProjectStatus({
@@ -124,7 +124,7 @@ jest.mock('../../../../api/quality-gates', () => {
});

jest.mock('../../../../api/time-machine', () => {
const { MetricKey } = require.requireActual('../../../../types/metrics');
const { MetricKey } = jest.requireActual('../../../../types/metrics');
return {
getAllTimeMachineData: jest.fn().mockResolvedValue({
measures: [
@@ -143,7 +143,7 @@ jest.mock('../../../../api/time-machine', () => {
});

jest.mock('../../../../api/projectActivity', () => {
const { mockAnalysis } = require.requireActual('../../../../helpers/testMocks');
const { mockAnalysis } = jest.requireActual('../../../../helpers/testMocks');
return {
getProjectActivity: jest.fn().mockResolvedValue({
analyses: [mockAnalysis(), mockAnalysis(), mockAnalysis(), mockAnalysis(), mockAnalysis()]
@@ -175,8 +175,8 @@ jest.mock('../../../../api/application', () => ({
}));

jest.mock('../../../../components/activity-graph/utils', () => {
const { MetricKey } = require.requireActual('../../../../types/metrics');
const { GraphType } = require.requireActual('../../../../types/project-activity');
const { MetricKey } = jest.requireActual('../../../../types/metrics');
const { GraphType } = jest.requireActual('../../../../types/project-activity');
return {
getActivityGraph: jest.fn(() => ({ graph: GraphType.coverage })),
saveActivityGraph: jest.fn(),

+ 1
- 1
server/sonar-web/src/main/js/apps/overview/pullRequests/__tests__/PullRequestOverview-test.tsx 查看文件

@@ -28,7 +28,7 @@ import { PR_METRICS } from '../../utils';
import { PullRequestOverview } from '../PullRequestOverview';

jest.mock('../../../../api/measures', () => {
const { mockMeasure, mockMetric } = require.requireActual('../../../../helpers/testMocks');
const { mockMeasure, mockMetric } = jest.requireActual('../../../../helpers/testMocks');
return {
getMeasuresWithMetrics: jest.fn().mockResolvedValue({
component: {

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/MetricBox-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import MetricBox, { MetricBoxProps } from '../MetricBox';

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/Report-test.tsx 查看文件

@@ -19,7 +19,7 @@
*/
/* eslint-disable import/first */
jest.mock('../../../../api/report', () => {
const report = require.requireActual('../../../../api/report');
const report = jest.requireActual('../../../../api/report');
report.getReportStatus = jest.fn(() => Promise.resolve({}));
return report;
});

+ 1
- 1
server/sonar-web/src/main/js/apps/portfolio/components/__tests__/Subscription-test.tsx 查看文件

@@ -19,7 +19,7 @@
*/
/* eslint-disable import/first */
jest.mock('../../../../api/report', () => {
const report = require.requireActual('../../../../api/report');
const report = jest.requireActual('../../../../api/report');
report.subscribe = jest.fn(() => Promise.resolve());
report.unsubscribe = jest.fn(() => Promise.resolve());
return report;

+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysesList-test.tsx 查看文件

@@ -32,7 +32,7 @@ jest.mock('date-fns/start_of_day', () => (date: Date) => {
});

jest.mock('sonar-ui-common/helpers/dates', () => {
const actual = require.requireActual('sonar-ui-common/helpers/dates');
const actual = jest.requireActual('sonar-ui-common/helpers/dates');
return { ...actual, toShortNotSoISOString: (date: string) => 'ISO.' + date };
});


+ 1
- 1
server/sonar-web/src/main/js/apps/projectActivity/components/__tests__/ProjectActivityAnalysis-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { mount, shallow } from 'enzyme';
import * as React from 'react';
import { IntlProvider } from 'react-intl';

+ 1
- 1
server/sonar-web/src/main/js/apps/projectBaseline/components/__tests__/BranchAnalysisListRenderer-test.tsx 查看文件

@@ -31,7 +31,7 @@ jest.mock('date-fns/start_of_day', () => (date: Date) => {
});

jest.mock('sonar-ui-common/helpers/dates', () => {
const actual = require.requireActual('sonar-ui-common/helpers/dates');
const actual = jest.requireActual('sonar-ui-common/helpers/dates');
return { ...actual, toShortNotSoISOString: (date: string) => `ISO.${date}` };
});


+ 13
- 14
server/sonar-web/src/main/js/apps/projectQualityGate/ProjectQualityGateApp.tsx 查看文件

@@ -76,22 +76,21 @@ export default class ProjectQualityGateApp extends React.PureComponent<Props, St

if (!qualityGate.isDefault) {
return false;
} else {
// If this is the default Quality Gate, check if it was explicitly
// selected, or if we're inheriting the system default.
/* eslint-disable-next-line sonarjs/prefer-immediate-return */
const selected = await searchProjects({
gateName: qualityGate.name,
query: component.key
}

// If this is the default Quality Gate, check if it was explicitly
// selected, or if we're inheriting the system default.
const selected = await searchProjects({
gateName: qualityGate.name,
query: component.key
})
.then(({ results }) => {
return Boolean(results.find(r => r.key === component.key)?.selected);
})
.then(({ results }) => {
return Boolean(results.find(r => r.key === component.key)?.selected);
})
.catch(() => false);
.catch(() => false);

// If it's NOT selected, it means we're following the system default.
return !selected;
}
// If it's NOT selected, it means we're following the system default.
return !selected;
};

fetchQualityGates = async () => {

+ 6
- 5
server/sonar-web/src/main/js/apps/projectQualityGate/__tests__/ProjectQualityGateAppRenderer-test.tsx 查看文件

@@ -52,13 +52,14 @@ it('should render correctly', () => {
});

it('should render select options correctly', () => {
return new Promise(resolve => {
return new Promise<void>(resolve => {
const wrapper = shallowRender();
const render = wrapper.find(Select).props().optionRenderer;
if (render) {
expect(render({ value: '1', label: 'Gate 1' })).toMatchSnapshot('default');
resolve();
}

expect(render).toBeDefined();

expect(render!({ value: '1', label: 'Gate 1' })).toMatchSnapshot('default');
resolve();
});
});


+ 31
- 33
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/AddLanguageModal-test.tsx 查看文件

@@ -29,39 +29,37 @@ it('should render correctly', () => {
});

it('should correctly handle changes', () => {
return new Promise(resolve => {
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit });

const langSelect = getLanguageSelect(wrapper);
let profileSelect = getProfileSelect(wrapper);

// Language select should only have 2; JS is not available. Profile Select
// should have none, as no language is selected yet.
expect(langSelect.props().options).toHaveLength(2);
expect(profileSelect.props().options).toHaveLength(0);

// Choose CSS.
const langChange = langSelect.props().onChange;
if (langChange) {
langChange({ value: 'css' });

// Should now show 2 available profiles.
profileSelect = getProfileSelect(wrapper);
expect(profileSelect.props().options).toHaveLength(2);

// Choose 1 profile.
const profileChange = profileSelect.props().onChange;
if (profileChange) {
profileChange({ value: 'css2' });

submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('css2');

resolve();
}
}
});
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit });

const langSelect = getLanguageSelect(wrapper);
let profileSelect = getProfileSelect(wrapper);

// Language select should only have 2; JS is not available. Profile Select
// should have none, as no language is selected yet.
expect(langSelect.props().options).toHaveLength(2);
expect(profileSelect.props().options).toHaveLength(0);

// Choose CSS.
const langChange = langSelect.props().onChange;

expect(langChange).toBeDefined();

langChange!({ value: 'css' });

// Should now show 2 available profiles.
profileSelect = getProfileSelect(wrapper);
expect(profileSelect.props().options).toHaveLength(2);

// Choose 1 profile.
const profileChange = profileSelect.props().onChange;

expect(profileChange).toBeDefined();

profileChange!({ value: 'css2' });

submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('css2');
});

function diveIntoSimpleModal(wrapper: ShallowWrapper) {

+ 30
- 35
server/sonar-web/src/main/js/apps/projectQualityProfiles/components/__tests__/SetQualityProfileModal-test.tsx 查看文件

@@ -32,48 +32,43 @@ it('should render correctly', () => {
});

it('should render select options correctly', () => {
return new Promise(resolve => {
const wrapper = shallowRender();
const render = wrapper.find(Select).props().optionRenderer;
if (render) {
expect(render({ value: 'bar', label: 'Profile 1' })).toMatchSnapshot('default');
resolve();
}
});
const wrapper = shallowRender();
const render = wrapper.find(Select).props().optionRenderer;

expect(render).toBeDefined();

expect(render!({ value: 'bar', label: 'Profile 1' })).toMatchSnapshot('default');
});

it('should correctly handle changes', () => {
return new Promise(resolve => {
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit }, false);
const onSubmit = jest.fn();
const wrapper = shallowRender({ onSubmit }, false);

diveIntoSimpleModal(wrapper)
.find(Radio)
.at(0)
.props()
.onCheck('');
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith(undefined, 'foo');
diveIntoSimpleModal(wrapper)
.find(Radio)
.at(0)
.props()
.onCheck('');
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith(undefined, 'foo');

diveIntoSimpleModal(wrapper)
.find(Radio)
.at(1)
.props()
.onCheck('');
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('foo', 'foo');

diveIntoSimpleModal(wrapper)
.find(Radio)
.at(1)
.props()
.onCheck('');
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('foo', 'foo');
const change = diveIntoSimpleModal(wrapper)
.find(Select)
.props().onChange;

const change = diveIntoSimpleModal(wrapper)
.find(Select)
.props().onChange;
if (change) {
change({ value: 'bar' });
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('bar', 'foo');
expect(change).toBeDefined();

resolve();
}
});
change!({ value: 'bar' });
submitSimpleModal(wrapper);
expect(onSubmit).toHaveBeenLastCalledWith('bar', 'foo');
});

function diveIntoSimpleModal(wrapper: ShallowWrapper) {

+ 1
- 1
server/sonar-web/src/main/js/apps/projects/components/__tests__/AllProjects-test.tsx 查看文件

@@ -50,7 +50,7 @@ jest.mock('../PageSidebar', () => ({
}));

jest.mock('../../utils', () => {
const utils = require.requireActual('../../utils');
const utils = jest.requireActual('../../utils');
utils.fetchProjects = jest.fn(() => Promise.resolve({ projects: [] }));
return utils;
});

+ 48
- 51
server/sonar-web/src/main/js/apps/projects/components/project-card/ProjectCard.tsx 查看文件

@@ -50,20 +50,18 @@ interface Props {
type?: string;
}

function renderFirstLine(props: Props) {
function renderFirstLine(project: Props['project'], handleFavorite: Props['handleFavorite']) {
const {
project: {
analysisDate,
tags,
qualifier,
isFavorite,
key,
name,
measures,
needIssueSync,
visibility
}
} = props;
analysisDate,
tags,
qualifier,
isFavorite,
key,
name,
measures,
needIssueSync,
visibility
} = project;

return (
<div className="display-flex-center">
@@ -73,7 +71,7 @@ function renderFirstLine(props: Props) {
className="spacer-right"
component={key}
favorite={isFavorite}
handleFavorite={props.handleFavorite}
handleFavorite={handleFavorite}
qualifier={qualifier}
/>
)}
@@ -134,10 +132,12 @@ function renderFirstLine(props: Props) {
);
}

function renderSecondLine(props: Props, isNewCode: boolean) {
const {
project: { measures }
} = props;
function renderSecondLine(
currentUser: Props['currentUser'],
project: Props['project'],
isNewCode: boolean
) {
const { measures } = project;

return (
<div
@@ -145,7 +145,7 @@ function renderSecondLine(props: Props, isNewCode: boolean) {
'project-card-leak': isNewCode
})}>
<div className="project-card-main big-padded-left big-padded-right big-padded-bottom">
{renderMeasures(props, isNewCode)}
{renderMeasures(currentUser, project, isNewCode)}
</div>
<div className="project-card-meta display-flex-end big-padded-left big-padded-right big-padded-bottom">
{isNewCode
@@ -187,11 +187,12 @@ function renderSecondLine(props: Props, isNewCode: boolean) {
);
}

function renderMeasures(props: Props, isNewCode: boolean) {
const {
currentUser,
project: { measures, needIssueSync, analysisDate, leakPeriodDate, qualifier, key }
} = props;
function renderMeasures(
currentUser: Props['currentUser'],
project: Props['project'],
isNewCode: boolean
) {
const { measures, needIssueSync, analysisDate, leakPeriodDate, qualifier, key } = project;

if (analysisDate && (!isNewCode || leakPeriodDate)) {
return (
@@ -202,44 +203,40 @@ function renderMeasures(props: Props, isNewCode: boolean) {
newCodeStartingDate={leakPeriodDate}
/>
);
} else {
return (
<div className="spacer-top spacer-bottom">
<span className="note">
{isNewCode && analysisDate
? translate('projects.no_new_code_period', qualifier)
: translate('projects.not_analyzed', qualifier)}
</span>
{qualifier !== ComponentQualifier.Application &&
!analysisDate &&
isLoggedIn(currentUser) &&
!needIssueSync && (
<Link className="button spacer-left" to={getProjectUrl(key)}>
{translate('projects.configure_analysis')}
</Link>
)}
</div>
);
}

return (
<div className="spacer-top spacer-bottom">
<span className="note">
{isNewCode && analysisDate
? translate('projects.no_new_code_period', qualifier)
: translate('projects.not_analyzed', qualifier)}
</span>
{qualifier !== ComponentQualifier.Application &&
!analysisDate &&
isLoggedIn(currentUser) &&
!needIssueSync && (
<Link className="button spacer-left" to={getProjectUrl(key)}>
{translate('projects.configure_analysis')}
</Link>
)}
</div>
);
}

export default function ProjectCard(props: Props) {
const {
height,
type,
project: { needIssueSync, key }
} = props;
const { currentUser, height, type, project } = props;
const isNewCode = type === 'leak';

return (
<div
className={classNames('display-flex-column boxed-group it_project_card', {
'project-card-disabled': needIssueSync
'project-card-disabled': project.needIssueSync
})}
data-key={key}
data-key={project.key}
style={{ height }}>
{renderFirstLine(props)}
{renderSecondLine(props, isNewCode)}
{renderFirstLine(project, props.handleFavorite)}
{renderSecondLine(currentUser, project, isNewCode)}
</div>
);
}

+ 1
- 3
server/sonar-web/src/main/js/apps/quality-profiles/changelog/__tests__/ChangelogContainer-test.tsx 查看文件

@@ -27,9 +27,7 @@ import { ChangelogContainer } from '../ChangelogContainer';
beforeEach(() => jest.clearAllMocks());

jest.mock('../../../../api/quality-profiles', () => {
const { mockQualityProfileChangelogEvent } = require.requireActual(
'../../../../helpers/testMocks'
);
const { mockQualityProfileChangelogEvent } = jest.requireActual('../../../../helpers/testMocks');
return {
getProfileChangelog: jest.fn().mockResolvedValue({
events: [

+ 1
- 1
server/sonar-web/src/main/js/apps/quality-profiles/details/__tests__/ProfilePermissionsFormSelect-test.tsx 查看文件

@@ -22,7 +22,7 @@ import * as React from 'react';
import ProfilePermissionsFormSelect from '../ProfilePermissionsFormSelect';

jest.mock('lodash', () => {
const lodash = require.requireActual('lodash');
const lodash = jest.requireActual('lodash');
lodash.debounce = (fn: Function) => (...args: any[]) => fn(...args);
return lodash;
});

+ 4
- 4
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/__snapshots__/HotspotOpenInIdeButton-test.tsx.snap 查看文件

@@ -6,7 +6,7 @@ exports[`HotspotOpenInIdeButton should handle several IDE 1`] = `
open={false}
overlay={
<DropdownOverlay>
<Unknown
<HotspotOpenInIdeOverlay
ides={Array []}
onIdeSelected={[Function]}
/>
@@ -31,7 +31,7 @@ exports[`HotspotOpenInIdeButton should handle several IDE: dropdown open 1`] = `
open={true}
overlay={
<DropdownOverlay>
<Unknown
<HotspotOpenInIdeOverlay
ides={
Array [
Object {
@@ -69,7 +69,7 @@ exports[`HotspotOpenInIdeButton should render correctly 1`] = `
open={false}
overlay={
<DropdownOverlay>
<Unknown
<HotspotOpenInIdeOverlay
ides={Array []}
onIdeSelected={[Function]}
/>
@@ -86,4 +86,4 @@ exports[`HotspotOpenInIdeButton should render correctly 1`] = `
/>
</Button>
</Toggler>
`;
`;

+ 1
- 1
server/sonar-web/src/main/js/apps/settings/components/__tests__/EmailForm-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { change, submit, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';

+ 1
- 1
server/sonar-web/src/main/js/apps/system/__tests__/utils-test.ts 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { mockClusterSysInfo, mockStandaloneSysInfo } from '../../../helpers/testMocks';
import { SystemUpgrade } from '../../../types/system';
import * as u from '../utils';

+ 5
- 6
server/sonar-web/src/main/js/components/SourceViewer/SourceViewerBase.tsx 查看文件

@@ -223,9 +223,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
const firstLine = sources[0];
const lastList = sources[sources.length - 1];
return lineNumber < firstLine.line || lineNumber > lastList.line;
} else {
return true;
}

return true;
}

fetchComponent() {
@@ -383,10 +383,9 @@ export default class SourceViewerBase extends React.PureComponent<Props, State>
// request one additional line to define `hasSourcesAfter`
to++;

return this.propsLoadSources(this.props.component, from, to, this.props.branchLike).then(
sources => resolve(sources),
onFailLoadSources
);
this.propsLoadSources(this.props.component, from, to, this.props.branchLike).then(sources => {
resolve(sources);
}, onFailLoadSources);
});
};


+ 7
- 0
server/sonar-web/src/main/js/components/SourceViewer/__tests__/SourceViewerBase-test.tsx 查看文件

@@ -146,6 +146,13 @@ it('should load sources after', async () => {
expect(wrapper.state().issues).toHaveLength(2);
});

it('should handle no sources when checking ranges', () => {
const wrapper = shallowRender();

wrapper.setState({ sources: undefined });
expect(wrapper.instance().isLineOutsideOfRange(12)).toBe(true);
});

function shallowRender(overrides: Partial<SourceViewerBase['props']> = {}) {
return shallow<SourceViewerBase>(
<SourceViewerBase branchLike={mockMainBranch()} component="my-component" {...overrides} />

+ 1
- 1
server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/LineSCM-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { LineSCM, LineSCMProps } from '../LineSCM';

+ 1
- 1
server/sonar-web/src/main/js/components/SourceViewer/components/__tests__/SCMPopup-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { SCMPopup, SCMPopupProps } from '../SCMPopup';

+ 1
- 1
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsHistory-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { parseDate } from 'sonar-ui-common/helpers/dates';

+ 1
- 1
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsTooltips-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { parseDate } from 'sonar-ui-common/helpers/dates';

+ 1
- 1
server/sonar-web/src/main/js/components/activity-graph/__tests__/GraphsTooltipsContentCoverage-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { shallow } from 'enzyme';
import * as React from 'react';
import { parseDate } from 'sonar-ui-common/helpers/dates';

+ 1
- 1
server/sonar-web/src/main/js/components/activity-graph/__tests__/utils-test.ts 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import * as dates from 'sonar-ui-common/helpers/dates';
import { MetricKey } from '../../../types/metrics';
import { GraphType, Serie } from '../../../types/project-activity';

+ 7
- 3
server/sonar-web/src/main/js/components/common/BranchStatus.tsx 查看文件

@@ -23,13 +23,16 @@ import Level from 'sonar-ui-common/components/ui/Level';
import { getBranchStatusByBranchLike, Store } from '../../store/rootReducer';
import { BranchLike } from '../../types/branch-like';

interface Props {
interface ExposedProps {
branchLike: BranchLike;
component: string;
}

interface BranchStatusProps {
status?: string;
}

export function BranchStatus({ status }: Props) {
export function BranchStatus({ status }: BranchStatusProps) {
if (!status) {
return null;
}
@@ -37,7 +40,8 @@ export function BranchStatus({ status }: Props) {
return <Level level={status} small={true} />;
}

const mapStateToProps = (state: Store, { branchLike, component }: Props) => {
const mapStateToProps = (state: Store, props: ExposedProps) => {
const { branchLike, component } = props;
const { status } = getBranchStatusByBranchLike(state, component, branchLike);
return { status };
};

+ 17
- 22
server/sonar-web/src/main/js/components/common/__tests__/AnalysisWarningsModal-test.tsx 查看文件

@@ -59,29 +59,24 @@ it('should fetch task warnings if it has to', async () => {
expect(getTask).toBeCalledWith('abcd1234', ['warnings']);
});

it('should correctly handle dismissing warnings', () => {
return new Promise(resolve => {
const onWarningDismiss = jest.fn();
const wrapper = shallowRender({
componentKey: 'foo',
onWarningDismiss,
warnings: [mockTaskWarning({ key: 'bar', dismissable: true })]
});

const click = wrapper.find('ButtonLink.link-base-color').props().onClick;
if (click) {
click(mockEvent());

waitAndUpdate(wrapper).then(
() => {
expect(dismissAnalysisWarning).toBeCalledWith('foo', 'bar');
expect(onWarningDismiss).toBeCalled();
resolve();
},
() => {}
);
}
it('should correctly handle dismissing warnings', async () => {
const onWarningDismiss = jest.fn();
const wrapper = shallowRender({
componentKey: 'foo',
onWarningDismiss,
warnings: [mockTaskWarning({ key: 'bar', dismissable: true })]
});

const click = wrapper.find('ButtonLink.link-base-color').props().onClick;

expect(click).toBeDefined();

click!(mockEvent());

await waitAndUpdate(wrapper);

expect(dismissAnalysisWarning).toBeCalledWith('foo', 'bar');
expect(onWarningDismiss).toBeCalled();
});

it('should correctly handle updates', async () => {

+ 1
- 2
server/sonar-web/src/main/js/components/common/__tests__/BranchStatus-test.tsx 查看文件

@@ -19,7 +19,6 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { mockBranch } from '../../../helpers/mocks/branch-like';
import { BranchStatus } from '../BranchStatus';

it('should render correctly', () => {
@@ -29,5 +28,5 @@ it('should render correctly', () => {
});

function shallowRender(status?: string) {
return shallow(<BranchStatus branchLike={mockBranch()} component="foo" status={status} />);
return shallow(<BranchStatus status={status} />);
}

+ 1
- 0
server/sonar-web/src/main/js/components/docs/DocCollapsibleBlock.tsx 查看文件

@@ -38,6 +38,7 @@ export default class DocCollapsibleBlock extends React.PureComponent<{}, State>
<a
aria-expanded={this.state.open}
aria-haspopup={true}
role="button"
className="link-no-underline"
href="#"
onClick={this.handleClick}>

+ 3
- 3
server/sonar-web/src/main/js/components/docs/__tests__/DocToc-test.tsx 查看文件

@@ -45,17 +45,17 @@ Risus placerat, efficitur enim ut, pellentesque sem. Mauris non lorem auctor, co
`;

jest.mock('remark', () => {
const remark = require.requireActual('remark');
const remark = jest.requireActual('remark');
return { default: remark };
});

jest.mock('remark-react', () => {
const remarkReact = require.requireActual('remark-react');
const remarkReact = jest.requireActual('remark-react');
return { default: remarkReact };
});

jest.mock('lodash', () => {
const lodash = require.requireActual('lodash');
const lodash = jest.requireActual('lodash');
lodash.debounce = (fn: any) => fn;
return lodash;
});

+ 2
- 0
server/sonar-web/src/main/js/components/docs/__tests__/__snapshots__/DocCollapsibleBlock-test.tsx.snap 查看文件

@@ -12,6 +12,7 @@ exports[`should render a collapsible block 1`] = `
className="link-no-underline"
href="#"
onClick={[Function]}
role="button"
>
<OpenCloseIcon
className="text-middle little-spacer-right"
@@ -32,6 +33,7 @@ exports[`should render a collapsible block 2`] = `
className="link-no-underline"
href="#"
onClick={[Function]}
role="button"
>
<OpenCloseIcon
className="text-middle little-spacer-right"

+ 1
- 1
server/sonar-web/src/main/js/components/measure/__tests__/Measure-test.tsx 查看文件

@@ -22,7 +22,7 @@ import * as React from 'react';
import Measure from '../Measure';

jest.mock('../../../helpers/measures', () => {
const measures = require.requireActual('../../../helpers/measures');
const measures = jest.requireActual('../../../helpers/measures');
measures.getRatingTooltip = jest.fn(() => 'tooltip');
return measures;
});

+ 1
- 0
server/sonar-web/src/main/js/components/tutorials/components/RenderOptions.tsx 查看文件

@@ -32,6 +32,7 @@ export interface RenderOptionsProps {

export default function RenderOptions({
checked,
name,
onCheck,
optionLabelKey,
options,

+ 3
- 3
server/sonar-web/src/main/js/components/tutorials/components/__tests__/__snapshots__/RenderOptions-test.tsx.snap 查看文件

@@ -6,7 +6,7 @@ exports[`should render correctly: default 1`] = `
>
<RadioToggle
disabled={false}
name=""
name="bar"
onCheck={[MockFunction]}
options={
Array [
@@ -31,7 +31,7 @@ exports[`should render correctly: option checked 1`] = `
>
<RadioToggle
disabled={false}
name=""
name="bar"
onCheck={[MockFunction]}
options={
Array [
@@ -61,7 +61,7 @@ exports[`should render correctly: with title 1`] = `
</h4>
<RadioToggle
disabled={false}
name=""
name="bar"
onCheck={[MockFunction]}
options={
Array [

+ 1
- 1
server/sonar-web/src/main/js/helpers/extensions.ts 查看文件

@@ -38,10 +38,10 @@ export async function getExtensionStart(key: string) {
}

if (!librariesExposed) {
librariesExposed = true;
// Async import allows to reduce initial vendor bundle size
const exposeLibraries = (await import('../app/components/extensions/exposeLibraries')).default;
exposeLibraries();
librariesExposed = true;
}

await installScript(`/static/${key}.js`);

+ 1
- 1
server/sonar-web/src/main/js/helpers/mocks/quality-gates.ts 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import {
QualityGateApplicationStatus,
QualityGateProjectStatus,

+ 1
- 1
server/sonar-web/src/main/js/helpers/testMocks.ts 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { Location } from 'history';
import { InjectedRouter } from 'react-router';
import { createStore, Store } from 'redux';

+ 2
- 4
server/sonar-web/src/main/js/store/__tests__/rootActions-test.tsx 查看文件

@@ -23,14 +23,12 @@ import { registerBranchStatusAction } from '../branches';
import { fetchBranchStatus, registerBranchStatus } from '../rootActions';

jest.mock('../branches', () => ({
...require.requireActual('../branches'),
...jest.requireActual('../branches'),
registerBranchStatusAction: jest.fn()
}));

jest.mock('../../api/quality-gates', () => {
const { mockQualityGateProjectStatus } = require.requireActual(
'../../helpers/mocks/quality-gates'
);
const { mockQualityGateProjectStatus } = jest.requireActual('../../helpers/mocks/quality-gates');
return {
getQualityGateProjectStatus: jest.fn().mockResolvedValue(
mockQualityGateProjectStatus({

+ 1
- 1
server/sonar-web/src/main/js/store/__tests__/rootReducers-test.tsx 查看文件

@@ -23,7 +23,7 @@ import { getBranchStatusByBranchLike, Store } from '../rootReducer';

jest.mock('../branches', () => {
return {
...require.requireActual('../branches'),
...jest.requireActual('../branches'),
getBranchStatusByBranchLike: jest.fn()
};
});

+ 1
- 1
server/sonar-web/src/main/js/store/__tests__/users-test.tsx 查看文件

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* eslint-disable sonarjs/no-duplicate-string */
import { mockCurrentUser, mockLoggedInUser, mockUser } from '../../helpers/testMocks';
import reducer, {
getCurrentUser,

+ 680
- 355
server/sonar-web/yarn.lock
文件差异内容过多而无法显示
查看文件


正在加载...
取消
保存