@@ -27,7 +27,14 @@ module.exports = { | |||
testRegex: '(/__tests__/.*|\\-test)\\.(ts|tsx|js)$', | |||
transform: { | |||
'\\.js$': 'babel-jest', | |||
'\\.(ts|tsx)$': 'ts-jest' | |||
'^.+\\.tsx?$': [ | |||
'@swc/jest', | |||
{ | |||
jsc: { | |||
target: 'es2018' | |||
} | |||
} | |||
] | |||
}, | |||
reporters: [ | |||
'default', |
@@ -60,6 +60,8 @@ | |||
"@babel/preset-env": "7.16.11", | |||
"@babel/preset-react": "7.16.7", | |||
"@emotion/jest": "11.7.1", | |||
"@swc/core": "1.2.157", | |||
"@swc/jest": "0.2.20", | |||
"@testing-library/dom": "8.11.3", | |||
"@testing-library/jest-dom": "5.16.2", | |||
"@testing-library/react": "12.1.2", | |||
@@ -117,7 +119,7 @@ | |||
"glob": "7.2.0", | |||
"glob-promise": "3.4.0", | |||
"http-proxy": "1.18.1", | |||
"jest": "27.4.7", | |||
"jest": "27.5.1", | |||
"jest-emotion": "10.0.32", | |||
"jest-junit": "13.0.0", | |||
"jsdom": "16.7.0", |
@@ -23,16 +23,22 @@ import Modal from '../../../components/controls/Modal'; | |||
import { mockEvent } from '../../../helpers/testMocks'; | |||
import KeyboardShortcutsModal from '../KeyboardShortcutsModal'; | |||
let handle: void | (() => void); | |||
beforeEach(() => { | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => { | |||
handle = f(); | |||
}); | |||
jest.mock('react', () => { | |||
let close: () => void; | |||
return { | |||
...jest.requireActual('react'), | |||
useEffect: jest.fn().mockImplementation(f => { | |||
close = f(); | |||
}), | |||
clean: () => { | |||
close(); | |||
} | |||
}; | |||
}); | |||
afterEach(() => { | |||
if (handle) { | |||
handle(); | |||
if ((React as any).clean as () => void) { | |||
(React as any).clean(); | |||
} | |||
}); | |||
@@ -29,9 +29,24 @@ import ComponentNav, { ComponentNavProps } from '../ComponentNav'; | |||
import Menu from '../Menu'; | |||
import InfoDrawer from '../projectInformation/InfoDrawer'; | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useEffect: jest.fn().mockImplementation(f => f()) | |||
}; | |||
}); | |||
jest.mock('../../../RecentHistory', () => { | |||
return { | |||
__esModule: true, | |||
default: class RecentHistory { | |||
static add = jest.fn(); | |||
} | |||
}; | |||
}); | |||
beforeEach(() => { | |||
jest.clearAllMocks(); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
}); | |||
it('renders correctly', () => { | |||
@@ -53,7 +68,6 @@ it('correctly adds data to the history if there are breadcrumbs', () => { | |||
const key = 'foo'; | |||
const name = 'Foo'; | |||
const qualifier = ComponentQualifier.Portfolio; | |||
const spy = jest.spyOn(RecentHistory, 'add'); | |||
shallowRender({ | |||
component: mockComponent({ | |||
@@ -69,7 +83,7 @@ it('correctly adds data to the history if there are breadcrumbs', () => { | |||
}) | |||
}); | |||
expect(spy).toBeCalledWith(key, name, qualifier.toLowerCase()); | |||
expect(RecentHistory.add).toBeCalledWith(key, name, qualifier.toLowerCase()); | |||
}); | |||
it('correctly toggles the project info display', () => { |
@@ -27,6 +27,13 @@ import AzurePersonalAccessTokenForm, { | |||
AzurePersonalAccessTokenFormProps | |||
} from '../AzurePersonalAccessTokenForm'; | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot('default'); | |||
expect(shallowRender({ submitting: true })).toMatchSnapshot('submitting'); | |||
@@ -51,7 +58,7 @@ it('should correctly handle form interactions', () => { | |||
// If validation fails, we toggle the submitting flag and call useEffect() | |||
// to set the `touched` flag to false again. Trigger a re-render, and mock | |||
// useEffect(). This should de-activate the submit button again. | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
wrapper.setProps({ submitting: false }); | |||
expect(wrapper.find(SubmitButton).prop('disabled')).toBe(true); | |||
}); |
@@ -33,9 +33,12 @@ import CreateProjectModeSelection from '../CreateProjectModeSelection'; | |||
import { CreateProjectPage } from '../CreateProjectPage'; | |||
import { CreateProjectModes } from '../types'; | |||
jest.mock('../../../../api/alm-settings', () => ({ | |||
getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.BitbucketServer, key: 'foo' }]) | |||
})); | |||
jest.mock('../../../../api/alm-settings', () => { | |||
const { AlmKeys } = jest.requireActual('../../../../types/alm-settings'); | |||
return { | |||
getAlmSettings: jest.fn().mockResolvedValue([{ alm: AlmKeys.BitbucketServer, key: 'foo' }]) | |||
}; | |||
}); | |||
beforeEach(jest.clearAllMocks); | |||
@@ -31,12 +31,6 @@ jest.mock('../../../../api/issues', () => ({ | |||
searchIssueTags: jest.fn().mockResolvedValue([undefined, []]) | |||
})); | |||
jest.mock('../BulkChangeModal', () => { | |||
const mock = jest.requireActual('../BulkChangeModal'); | |||
mock.MAX_PAGE_SIZE = 1; | |||
return mock; | |||
}); | |||
jest.mock('../../utils', () => ({ | |||
searchAssignees: jest.fn().mockResolvedValue({ | |||
results: [ |
@@ -109,7 +109,7 @@ exports[`should display form when issues are present 1`] = ` | |||
exports[`should display warning when too many issues are passed 1`] = ` | |||
<h2> | |||
issue_bulk_change.form.title.1 | |||
issue_bulk_change.form.title.500 | |||
</h2> | |||
`; | |||
@@ -123,7 +123,7 @@ exports[`should display warning when too many issues are passed 2`] = ` | |||
values={ | |||
Object { | |||
"max": <strong> | |||
1 | |||
500 | |||
</strong>, | |||
} | |||
} |
@@ -40,6 +40,14 @@ beforeEach(() => { | |||
jest.clearAllMocks(); | |||
}); | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useRef: jest.fn(), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot(); | |||
expect( | |||
@@ -97,9 +105,9 @@ describe('side effect', () => { | |||
const fakeParent = document.createElement('div'); | |||
beforeEach(() => { | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
jest.spyOn(document, 'querySelector').mockImplementationOnce(() => fakeElement); | |||
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: fakeParent })); | |||
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: fakeParent })); | |||
}); | |||
it('should trigger scrolling', () => { | |||
@@ -117,7 +125,7 @@ describe('side effect', () => { | |||
}); | |||
it('should not trigger scrolling if no parent', () => { | |||
const mockUseRef = jest.spyOn(React, 'useRef'); | |||
const mockUseRef = React.useRef as jest.Mock; | |||
mockUseRef.mockReset(); | |||
mockUseRef.mockImplementationOnce(() => ({ current: null })); | |||
shallowRender({ selectedHotspot: mockRawHotspot() }); |
@@ -28,6 +28,14 @@ import { | |||
HotspotPrimaryLocationBoxProps | |||
} from '../HotspotPrimaryLocationBox'; | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useRef: jest.fn(), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot('User logged in'); | |||
expect(shallowRender({ currentUser: mockCurrentUser() })).toMatchSnapshot('User not logged in '); | |||
@@ -55,8 +63,8 @@ it('should handle click', () => { | |||
it('should scroll on load if no secondary locations selected', () => { | |||
const node = document.createElement('div'); | |||
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: node })); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: node })); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
const scroll = jest.fn(); | |||
shallowRender({ scroll }); | |||
@@ -66,8 +74,8 @@ it('should scroll on load if no secondary locations selected', () => { | |||
it('should not scroll on load if a secondary location is selected', () => { | |||
const node = document.createElement('div'); | |||
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: node })); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: node })); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
const scroll = jest.fn(); | |||
shallowRender({ scroll, secondaryLocationSelected: true }); | |||
@@ -76,8 +84,8 @@ it('should not scroll on load if a secondary location is selected', () => { | |||
}); | |||
it('should not scroll on load if node is not defined', () => { | |||
jest.spyOn(React, 'useRef').mockImplementationOnce(() => ({ current: undefined })); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useRef as jest.Mock).mockImplementationOnce(() => ({ current: undefined })); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
const scroll = jest.fn(); | |||
shallowRender({ scroll }); |
@@ -28,6 +28,13 @@ import { mockUser } from '../../../../helpers/testMocks'; | |||
import HotspotCommentPopup from '../HotspotCommentPopup'; | |||
import HotspotReviewHistory, { HotspotReviewHistoryProps } from '../HotspotReviewHistory'; | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useState: jest.fn().mockImplementation(() => ['', jest.fn()]) | |||
}; | |||
}); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot('default'); | |||
expect(shallowRender({ showFullHistory: true })).toMatchSnapshot('show full list'); | |||
@@ -46,7 +53,7 @@ it('should render correctly', () => { | |||
it('should correctly handle comment updating', () => { | |||
return new Promise<void>((resolve, reject) => { | |||
const setEditedCommentKey = jest.fn(); | |||
jest.spyOn(React, 'useState').mockImplementationOnce(() => ['', setEditedCommentKey]); | |||
(React.useState as jest.Mock).mockImplementationOnce(() => ['', setEditedCommentKey]); | |||
const onEditComment = jest.fn(); | |||
const wrapper = shallowRender({ onEditComment, showFullHistory: true }); | |||
@@ -102,7 +109,7 @@ it('should correctly handle comment updating', () => { | |||
it('should correctly handle comment deleting', () => { | |||
return new Promise<void>((resolve, reject) => { | |||
const setEditedCommentKey = jest.fn(); | |||
jest.spyOn(React, 'useState').mockImplementationOnce(() => ['', setEditedCommentKey]); | |||
(React.useState as jest.Mock).mockImplementationOnce(() => ['', setEditedCommentKey]); | |||
const onDeleteComment = jest.fn(); | |||
const wrapper = shallowRender({ onDeleteComment, showFullHistory: true }); |
@@ -18,7 +18,7 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { shallow } from 'enzyme'; | |||
import React from 'react'; | |||
import * as React from 'react'; | |||
import { mockDefinition } from '../../../../helpers/mocks/settings'; | |||
import { scrollToElement } from '../../../../helpers/scrolling'; | |||
import SettingsSearchRenderer, { SettingsSearchRendererProps } from '../SettingsSearchRenderer'; | |||
@@ -27,6 +27,14 @@ jest.mock('../../../../helpers/scrolling', () => ({ | |||
scrollToElement: jest.fn() | |||
})); | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useRef: jest.fn(), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
afterAll(() => { | |||
jest.clearAllMocks(); | |||
}); | |||
@@ -52,11 +60,10 @@ it('should scroll to selected element', () => { | |||
const selected = {}; | |||
const selectedRef = { current: selected }; | |||
jest | |||
.spyOn(React, 'useRef') | |||
(React.useRef as jest.Mock) | |||
.mockImplementationOnce(() => scrollableRef) | |||
.mockImplementationOnce(() => selectedRef); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
shallowRender(); | |||
@@ -18,9 +18,17 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { shallow } from 'enzyme'; | |||
import React from 'react'; | |||
import * as React from 'react'; | |||
import { LineCoverage, LineCoverageProps } from '../LineCoverage'; | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useRef: jest.fn(), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
it('should render correctly', () => { | |||
expect(shallowRender()).toMatchSnapshot('covered'); | |||
expect(shallowRender({ line: { line: 3, coverageStatus: 'uncovered' } })).toMatchSnapshot( | |||
@@ -39,8 +47,8 @@ it('should render correctly', () => { | |||
it('should correctly trigger a scroll', () => { | |||
const element = { current: {} }; | |||
jest.spyOn(React, 'useEffect').mockImplementation(f => f()); | |||
jest.spyOn(React, 'useRef').mockImplementation(() => element); | |||
(React.useEffect as jest.Mock).mockImplementation(f => f()); | |||
(React.useRef as jest.Mock).mockImplementation(() => element); | |||
const scroll = jest.fn(); | |||
shallowRender({ scroll, scrollToUncoveredLine: true }); |
@@ -32,9 +32,16 @@ jest.mock('../../../helpers/storage', () => ({ | |||
save: jest.fn() | |||
})); | |||
jest.mock('react', () => { | |||
return { | |||
...jest.requireActual('react'), | |||
useEffect: jest.fn() | |||
}; | |||
}); | |||
beforeEach(() => { | |||
jest.clearAllMocks(); | |||
jest.spyOn(React, 'useEffect').mockImplementationOnce(f => f()); | |||
(React.useEffect as jest.Mock).mockImplementationOnce(f => f()); | |||
}); | |||
it('should render correctly', () => { |