Skip to content

Commit f2b9f22

Browse files
authored
Merge pull request #513 from nicolethoen/chore/update-unit-tests
chore: update unit tests to RTL
2 parents 318c7ef + f162214 commit f2b9f22

17 files changed

+552
-628
lines changed

__mocks__/domPolyfills.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* eslint-disable */
2+
3+
// Polyfill for Element.prototype.getRootNode (missing in older jsdom)
4+
if (!Element.prototype.getRootNode) {
5+
Element.prototype.getRootNode = function (options) {
6+
var node = this;
7+
while (node.parentNode) {
8+
node = node.parentNode;
9+
}
10+
return node;
11+
};
12+
}
13+
14+
// Polyfill for Element.prototype.closest (missing in older jsdom)
15+
if (!Element.prototype.closest) {
16+
Element.prototype.closest = function (selector) {
17+
var el = this;
18+
while (el) {
19+
if (el.matches && el.matches(selector)) {
20+
return el;
21+
}
22+
el = el.parentElement;
23+
}
24+
return null;
25+
};
26+
}

before-tests.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,34 @@
11
/* eslint-env node */
22

3-
import { configure } from 'enzyme';
4-
import * as Adapter from 'enzyme-adapter-react-16';
5-
63
import 'url-search-params-polyfill';
74

8-
// http://airbnb.io/enzyme/docs/installation/index.html#working-with-react-16
9-
configure({ adapter: new Adapter() });
5+
// Suppress act() warnings only for async markdown rendering (SyncMarkdownView /
6+
// QuickStartMarkdownView). Other act warnings still surface so new tests stay honest.
7+
const originalError = console.error;
8+
9+
const isMarkdownActWarning = (...args) => {
10+
const message = args
11+
.map((a) => {
12+
if (typeof a === 'string') {
13+
return a;
14+
}
15+
if (a instanceof Error && typeof a.message === 'string') {
16+
return a.message;
17+
}
18+
return '';
19+
})
20+
.join('\n');
21+
if (!message.includes('was not wrapped in act(')) {
22+
return false;
23+
}
24+
return (
25+
message.includes('SyncMarkdownView') || message.includes('QuickStartMarkdownView')
26+
);
27+
};
28+
29+
console.error = (...args) => {
30+
if (isMarkdownActWarning(...args)) {
31+
return;
32+
}
33+
originalError.call(console, ...args);
34+
};

jest-setup-framework.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require('@testing-library/jest-dom');

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@
102102
"./__mocks__/serverFlags.js",
103103
"./__mocks__/mutationObserver.js",
104104
"./__mocks__/websocket.js",
105-
"./before-tests.js"
105+
"./before-tests.js",
106+
"./__mocks__/domPolyfills.js"
106107
],
107108
"coverageDirectory": "__coverage__",
108109
"coverageReporters": [
@@ -115,7 +116,8 @@
115116
"src/**/*.{js,jsx,ts,tsx}",
116117
"!**/node_modules/**"
117118
],
118-
"resolver": "./jest-resolver.js"
119+
"resolver": "./jest-resolver.js",
120+
"setupTestFrameworkScriptFile": "./jest-setup-framework.js"
119121
},
120122
"engines": {
121123
"node": ">=18.0.0"

packages/module/package.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,16 @@
6666
"@rollup/plugin-commonjs": "^17.0.0",
6767
"@rollup/plugin-json": "^4.1.0",
6868
"@rollup/plugin-node-resolve": "^11.1.0",
69+
"@testing-library/jest-dom": "^6.9.1",
6970
"@testing-library/react": "^13.4.0",
7071
"@types/dompurify": "^3.0.5",
71-
"@types/enzyme": "^3.10.7",
72-
"@types/enzyme-adapter-react-16": "^1.0.6",
7372
"@types/history": "^4.7.8",
7473
"@types/node": "^14.14.35",
7574
"@types/react": "^18.2.79",
7675
"@types/react-dom": "^18.0.0",
7776
"clean-css-cli": "^4.3.0",
7877
"concat-files": "^0.1.1",
7978
"dart-sass": "^1.25.0",
80-
"enzyme": "^3.7.0",
81-
"enzyme-adapter-react-16": "^1.15.5",
82-
"enzyme-to-json": "^3.6.1",
8379
"monaco-editor": "0.34.1",
8480
"node-sass-glob-importer": "^5.3.2",
8581
"prettier": "^2.8.8",
Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,38 @@
1-
import { shallow } from 'enzyme';
2-
import MarkdownCopyClipboard, { CopyClipboard } from '../MarkdownCopyClipboard';
1+
import { render } from '@testing-library/react';
2+
import {
3+
QuickStartContext,
4+
QuickStartContextDefaults,
5+
} from '@quickstarts/utils/quick-start-context';
6+
import MarkdownCopyClipboard from '../MarkdownCopyClipboard';
7+
import { MARKDOWN_COPY_BUTTON_ID } from '../const';
38
import { htmlDocumentForCopyClipboard } from './test-data';
49

10+
const contextValues = {
11+
...QuickStartContextDefaults,
12+
getResource: (key: string) => key,
13+
};
14+
515
describe('MarkdownCopyClipboard', () => {
616
beforeAll(() => {
717
document.body.innerHTML = htmlDocumentForCopyClipboard;
818
});
19+
920
it('should render null if no element is found', () => {
10-
const wrapper = shallow(
11-
<MarkdownCopyClipboard docContext={document} rootSelector="#copy-markdown-3" />,
21+
const { container } = render(
22+
<QuickStartContext.Provider value={contextValues}>
23+
<MarkdownCopyClipboard docContext={document} rootSelector="#copy-markdown-3" />
24+
</QuickStartContext.Provider>,
1225
);
13-
expect(wrapper.isEmptyRender()).toBe(true);
14-
expect(wrapper.find(CopyClipboard).exists()).toBe(false);
26+
expect(container.firstChild).toBeNull();
1527
});
1628

17-
it('should render null if no element is found', () => {
18-
const wrapper = shallow(
19-
<MarkdownCopyClipboard docContext={document} rootSelector="#copy-markdown-1" />,
29+
it('should render copy targets when rootSelector matches buttons in the document', () => {
30+
render(
31+
<QuickStartContext.Provider value={contextValues}>
32+
<MarkdownCopyClipboard docContext={document} rootSelector="#copy-markdown-1" />
33+
</QuickStartContext.Provider>,
2034
);
21-
expect(wrapper.isEmptyRender()).toBe(false);
22-
expect(wrapper.find(CopyClipboard).exists()).toBe(true);
35+
const elements = document.querySelectorAll(`#copy-markdown-1 [${MARKDOWN_COPY_BUTTON_ID}]`);
36+
expect(elements).toHaveLength(2);
2337
});
2438
});
Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,39 @@
1-
import { Gallery, Card } from '@patternfly/react-core';
2-
import { shallow } from 'enzyme';
3-
import { EmptyBox } from '@console/internal/components/utils';
1+
import { render, screen, waitFor } from '@testing-library/react';
42
import { getQuickStarts } from '../../data/test-utils';
5-
import { QuickStartCatalogPage } from '../../QuickStartCatalogPage';
3+
import { QuickStartContext, QuickStartContextDefaults } from '../../utils/quick-start-context';
64
import QuickStartCatalog from '../QuickStartCatalog';
75

8-
jest.mock('@console/shared', () => {
9-
const ActualShared = require.requireActual('@console/shared');
10-
return {
11-
...ActualShared,
12-
useQueryParams: () => new Map(),
13-
};
14-
});
6+
const contextValues = {
7+
...QuickStartContextDefaults,
8+
activeQuickStartID: '',
9+
allQuickStartStates: {},
10+
getResource: (key: string) => key,
11+
};
12+
13+
const renderWithContext = (props: any) =>
14+
render(
15+
<QuickStartContext.Provider value={contextValues}>
16+
<QuickStartCatalog {...props} />
17+
</QuickStartContext.Provider>,
18+
);
1519

1620
describe('QuickStartCatalog', () => {
17-
it('should load an emptybox if no QS exist', () => {
18-
const QuickStartCatalogProps = { quickStarts: [], onClick: jest.fn() };
19-
const QuickStartCatalogWrapper = shallow(<QuickStartCatalogPage {...QuickStartCatalogProps} />);
20-
expect(QuickStartCatalogWrapper.find(EmptyBox).exists()).toBeTruthy();
21+
it('should render an empty state if no QS exist', () => {
22+
renderWithContext({ quickStarts: [] });
23+
// When no quickstarts, the catalog renders no cards
24+
expect(screen.queryByRole('article')).not.toBeInTheDocument();
2125
});
22-
it('should load a gallery if QS exist', () => {
23-
const QuickStartCatalogProps = { quickStarts: getQuickStarts(), onClick: jest.fn() };
24-
const QuickStartCatalogWrapper = shallow(<QuickStartCatalog {...QuickStartCatalogProps} />);
25-
expect(QuickStartCatalogWrapper.find(Gallery).exists()).toBeTruthy();
26-
});
27-
xit('should load galleryItems equal to the number of QS', () => {
28-
const QuickStartCatalogProps = { quickStarts: getQuickStarts(), onClick: jest.fn() };
29-
const QuickStartCatalogWrapper = shallow(<QuickStartCatalog {...QuickStartCatalogProps} />);
30-
const galleryItems = QuickStartCatalogWrapper.find(Card);
31-
expect(galleryItems.exists()).toBeTruthy();
32-
expect(galleryItems.length).toEqual(getQuickStarts().length);
26+
27+
it('should load a gallery if QS exist', async () => {
28+
const quickStarts = getQuickStarts();
29+
renderWithContext({ quickStarts });
30+
// Each tile exposes the quick start display name as the title control (link-styled button)
31+
await waitFor(() => {
32+
quickStarts.forEach((qs) => {
33+
expect(
34+
screen.getByRole('button', { name: qs.spec.displayName }),
35+
).toBeInTheDocument();
36+
});
37+
});
3338
});
3439
});
Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,56 @@
1-
import { Card } from '@patternfly/react-core';
2-
import { shallow } from 'enzyme';
1+
import { render, screen, waitFor } from '@testing-library/react';
32
import { getQuickStarts } from '../../data/test-utils';
43
import { QuickStartStatus } from '../../utils/quick-start-types';
4+
import { QuickStartContext, QuickStartContextDefaults } from '../../utils/quick-start-context';
55
import QuickStartTile from '../QuickStartTile';
66

7-
describe('QuickStartTile', () => {
8-
const quickstarts = getQuickStarts();
7+
const contextValues = {
8+
...QuickStartContextDefaults,
9+
activeQuickStartID: '',
10+
setActiveQuickStart: jest.fn(),
11+
getResource: (key: string) => key,
12+
};
13+
14+
const quickstarts = getQuickStarts();
915

10-
it('should load proper catalog tile without featured property', () => {
11-
const wrapper = shallow(
12-
<QuickStartTile
13-
quickStart={quickstarts[0]}
14-
status={QuickStartStatus.NOT_STARTED}
15-
onClick={jest.fn()}
16-
isActive={false}
17-
/>,
18-
);
19-
const catalogTile = wrapper.find(Card);
20-
expect(catalogTile.exists()).toBeTruthy();
21-
expect(catalogTile.hasClass('pf-m-current')).toBe(false);
16+
const renderWithContext = (props: any) =>
17+
render(
18+
<QuickStartContext.Provider value={contextValues}>
19+
<QuickStartTile {...props} />
20+
</QuickStartContext.Provider>,
21+
);
22+
23+
describe('QuickStartTile', () => {
24+
it('should load proper catalog tile without featured property', async () => {
25+
const quickStart = quickstarts[0];
26+
renderWithContext({
27+
quickStart,
28+
status: QuickStartStatus.NOT_STARTED,
29+
onClick: jest.fn(),
30+
isActive: false,
31+
});
32+
await waitFor(() => {
33+
expect(
34+
screen.getByRole('button', { name: quickStart.spec.displayName }),
35+
).toBeInTheDocument();
36+
});
37+
// Status label is omitted for not-started tiles
38+
expect(screen.queryByText('In progress')).not.toBeInTheDocument();
2239
});
2340

24-
it('should load proper catalog tile with featured property', () => {
25-
const wrapper = shallow(
26-
<QuickStartTile
27-
quickStart={quickstarts[1]}
28-
status={QuickStartStatus.IN_PROGRESS}
29-
onClick={jest.fn()}
30-
isActive
31-
/>,
32-
);
33-
const catalogTile = wrapper.find(Card);
34-
expect(catalogTile.exists()).toBeTruthy();
35-
expect(catalogTile.hasClass('pf-m-current')).toBe(true);
41+
it('should load proper catalog tile with featured property', async () => {
42+
const quickStart = quickstarts[1];
43+
renderWithContext({
44+
quickStart,
45+
status: QuickStartStatus.IN_PROGRESS,
46+
onClick: jest.fn(),
47+
isActive: true,
48+
});
49+
await waitFor(() => {
50+
expect(
51+
screen.getByRole('button', { name: quickStart.spec.displayName }),
52+
).toBeInTheDocument();
53+
});
54+
expect(screen.getByText('In progress')).toBeInTheDocument();
3655
});
3756
});
Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,44 @@
1-
import { Popover } from '@patternfly/react-core';
2-
import { shallow } from 'enzyme';
1+
import { render, screen, waitFor } from '@testing-library/react';
32
import { getQuickStarts } from '../../data/test-utils';
3+
import { QuickStartContext, QuickStartContextDefaults } from '../../utils/quick-start-context';
44
import QuickStartTileDescription from '../QuickStartTileDescription';
55

6-
jest.mock('react', () => {
7-
const ActualReact = require.requireActual('react');
8-
return {
9-
...ActualReact,
10-
useContext: () => jest.fn(),
11-
};
12-
});
6+
const contextValues = {
7+
...QuickStartContextDefaults,
8+
activeQuickStartID: '',
9+
startQuickStart: jest.fn(),
10+
restartQuickStart: jest.fn(),
11+
getResource: (key: string) => key,
12+
};
1313

14-
xdescribe('QuickStartCatalog', () => {
15-
beforeEach(() => {
16-
spyOn(React, 'useContext').and.returnValue({
17-
activeQuickStartID: '',
18-
startQuickStart: () => {},
19-
restartQuickStart: () => {},
20-
getResource: (key) => `quickstart~${key}`,
21-
});
22-
});
14+
const renderWithContext = (props: any) =>
15+
render(
16+
<QuickStartContext.Provider value={contextValues}>
17+
<QuickStartTileDescription {...props} />
18+
</QuickStartContext.Provider>,
19+
);
2320

24-
it('should show prerequisites only if provided', () => {
25-
// this quick start does not have prereqs
21+
describe('QuickStartTileDescription', () => {
22+
it('should show prerequisites only if provided', async () => {
2623
const quickStart = getQuickStarts()[0].spec;
27-
const QuickStartTileDescriptionWrapper = shallow(
28-
<QuickStartTileDescription description={quickStart.description} />,
29-
);
30-
expect(QuickStartTileDescriptionWrapper.find(Text)).toHaveLength(0);
24+
renderWithContext({ description: quickStart.description });
25+
await waitFor(() => {
26+
expect(
27+
screen.queryByRole('button', { name: 'Show prerequisites' }),
28+
).not.toBeInTheDocument();
29+
});
3130
});
3231

33-
it('shoould render prerequisites inside a popover', () => {
32+
it('should render prerequisites trigger when prerequisite list is non-empty', async () => {
3433
const quickStart = getQuickStarts()[2].spec;
35-
const QuickStartTileDescriptionWrapper = shallow(
36-
<QuickStartTileDescription
37-
description={quickStart.description}
38-
prerequisites={quickStart.prerequisites}
39-
/>,
40-
);
41-
expect(QuickStartTileDescriptionWrapper.find(Popover)).toHaveLength(1);
34+
renderWithContext({
35+
description: quickStart.description,
36+
prerequisites: quickStart.prerequisites,
37+
});
38+
await waitFor(() => {
39+
expect(
40+
screen.getByRole('button', { name: 'Show prerequisites' }),
41+
).toBeInTheDocument();
42+
});
4243
});
4344
});

0 commit comments

Comments
 (0)