Skip to content

Commit

Permalink
Chore: convert last test to RTL and remove Enzyme references (grafana…
Browse files Browse the repository at this point in the history
…#61918)

convert last test to RTL and remove enzyme references
  • Loading branch information
ashharrison90 authored Jan 24, 2023
1 parent 479da46 commit 92a750a
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 452 deletions.
14 changes: 0 additions & 14 deletions .betterer.results
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@
// If this file contains merge conflicts, use `betterer merge` to automatically resolve them:
// https://phenomnomnominal.github.io/betterer/docs/results-file/#merge
//
exports[`no enzyme tests`] = {
value: `{
"packages/grafana-ui/src/components/QueryField/QueryField.test.tsx:2976628669": [
[0, 26, 13, "RegExp match", "2409514259"]
]
}`
};

exports[`better eslint`] = {
value: `{
"e2e/benchmarks/live/4-20hz-panels.spec.ts:5381": [
Expand Down Expand Up @@ -1315,12 +1307,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/QueryField/QueryField.test.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"],
[0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"packages/grafana-ui/src/components/QueryField/QueryField.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "1"]
Expand Down
3 changes: 0 additions & 3 deletions .betterer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { regexp } from '@betterer/regexp';
import { BettererFileTest } from '@betterer/betterer';
import { ESLint, Linter } from 'eslint';
import { existsSync } from 'fs';
import { exec } from 'child_process';
import path from 'path';
import glob from 'glob';

export default {
'no enzyme tests': () => regexp(/from 'enzyme'/g).include('**/*.test.*'),
'better eslint': () => countEslintErrors().include('**/*.{ts,tsx}'),
'no undocumented stories': () => countUndocumentedStories().include('**/*.story.tsx'),
};
Expand Down
1 change: 0 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ module.exports = {
testTimeout: 30000,
resolver: `<rootDir>/public/test/jest-resolver.js`,
setupFilesAfterEnv: ['./public/test/setupTests.ts'],
snapshotSerializers: ['enzyme-to-json/serializer'],
globals: {
__webpack_public_path__: '', // empty string
},
Expand Down
5 changes: 0 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,6 @@
"@types/d3-force": "^2.1.0",
"@types/d3-scale-chromatic": "1.3.1",
"@types/debounce-promise": "3.1.5",
"@types/enzyme": "3.10.12",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/eslint": "8.4.9",
"@types/file-saver": "2.0.5",
"@types/glob": "^8.0.0",
Expand Down Expand Up @@ -167,7 +165,6 @@
"@types/uuid": "8.3.4",
"@typescript-eslint/eslint-plugin": "5.42.0",
"@typescript-eslint/parser": "5.42.0",
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
"autoprefixer": "10.4.13",
"babel-jest": "29.3.1",
"babel-loader": "9.1.0",
Expand All @@ -179,8 +176,6 @@
"css-loader": "6.7.1",
"css-minimizer-webpack-plugin": "4.2.2",
"cypress": "9.5.1",
"enzyme": "3.11.0",
"enzyme-to-json": "3.6.2",
"esbuild": "0.16.17",
"esbuild-loader": "2.21.0",
"esbuild-plugin-browserslist": "^0.6.0",
Expand Down
9 changes: 1 addition & 8 deletions packages/grafana-toolkit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,7 @@ Yes! grafana-toolkit supports TypeScript by default.

grafana-toolkit comes with Jest as a test runner.

Internally at Grafana we use Enzyme. If you are developing React plugin and you want to configure Enzyme as a testing utility, then you need to configure `enzyme-adapter-react`. To do so, create `<YOUR_PLUGIN_DIR>/config/jest-setup.ts` file that will provide necessary setup. Copy the following code into that file to get Enzyme working with React:

```ts
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

configure({ adapter: new Adapter() });
```
Internally at Grafana we use React Testing Library.

You can also set up Jest with shims of your needs by creating `jest-shim.ts` file in the same directory: `<YOUR_PLUGIN_DIR_>/config/jest-shim.ts`

Expand Down
4 changes: 0 additions & 4 deletions packages/grafana-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,6 @@
"@testing-library/user-event": "14.4.3",
"@types/common-tags": "^1.8.0",
"@types/d3": "7.4.0",
"@types/enzyme": "3.10.12",
"@types/enzyme-adapter-react-16": "1.0.6",
"@types/hoist-non-react-statics": "3.3.1",
"@types/is-hotkey": "0.1.7",
"@types/jest": "29.2.3",
Expand All @@ -168,11 +166,9 @@
"@types/testing-library__jest-dom": "5.14.5",
"@types/tinycolor2": "1.4.3",
"@types/uuid": "8.3.4",
"@wojtekmaj/enzyme-adapter-react-17": "0.8.0",
"common-tags": "1.8.2",
"css-loader": "6.7.1",
"csstype": "3.1.1",
"enzyme": "3.11.0",
"esbuild": "0.16.17",
"expose-loader": "4.0.0",
"mock-raf": "1.0.1",
Expand Down
177 changes: 79 additions & 98 deletions packages/grafana-ui/src/components/QueryField/QueryField.test.tsx
Original file line number Diff line number Diff line change
@@ -1,127 +1,108 @@
import { mount, shallow } from 'enzyme';
import { render } from '@testing-library/react';
import React from 'react';
import { Editor } from 'slate-react';

import { createTheme } from '@grafana/data';

import { UnThemedQueryField } from './QueryField';

describe('<QueryField />', () => {
it('should render with null initial value', () => {
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query={null} onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
expect(() =>
render(
<UnThemedQueryField theme={createTheme()} query={null} onTypeahead={jest.fn()} portalOrigin="mock-origin" />
)
).not.toThrow();
});

it('should render with empty initial value', () => {
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query="" onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
expect(() =>
render(<UnThemedQueryField theme={createTheme()} query="" onTypeahead={jest.fn()} portalOrigin="mock-origin" />)
).not.toThrow();
});

it('should render with initial value', () => {
const wrapper = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" onTypeahead={jest.fn()} portalOrigin="mock-origin" />
);
expect(wrapper.find('div').exists()).toBeTruthy();
expect(() =>
render(
<UnThemedQueryField theme={createTheme()} query="my query" onTypeahead={jest.fn()} portalOrigin="mock-origin" />
)
).not.toThrow();
});

it('should execute query on blur', () => {
const onRun = jest.fn();
const wrapper = mount(
<UnThemedQueryField
theme={createTheme()}
query="my query"
onTypeahead={jest.fn()}
onRunQuery={onRun}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as UnThemedQueryField;
const ed = wrapper.find(Editor).instance() as Editor;
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(undefined, ed, () => {});
expect(onRun.mock.calls.length).toBe(1);
});

it('should run onChange with clean text', () => {
const onChange = jest.fn();
const wrapper = shallow(
<UnThemedQueryField
theme={createTheme()}
query={`my\r clean query `}
onTypeahead={jest.fn()}
onChange={onChange}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as UnThemedQueryField;
field.runOnChange();
expect(onChange.mock.calls.length).toBe(1);
expect(onChange.mock.calls[0][0]).toBe('my clean query ');
});

it('should run custom on blur, but not necessarily execute query', () => {
const onBlur = jest.fn();
const onRun = jest.fn();
const wrapper = mount(
<UnThemedQueryField
theme={createTheme()}
query="my query"
onTypeahead={jest.fn()}
onBlur={onBlur}
onRunQuery={onRun}
portalOrigin="mock-origin"
/>
);
const field = wrapper.instance() as UnThemedQueryField;
const ed = wrapper.find(Editor).instance() as Editor;
expect(onBlur.mock.calls.length).toBe(0);
expect(onRun.mock.calls.length).toBe(0);
field.handleBlur(undefined, ed, () => {});
expect(onBlur.mock.calls.length).toBe(1);
expect(onRun.mock.calls.length).toBe(0);
});
describe('syntaxLoaded', () => {
it('should re-render the editor after syntax has fully loaded', () => {
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
const mockOnRichValueChange = jest.fn();
const { rerender } = render(
<UnThemedQueryField
theme={createTheme()}
query="my query"
onRichValueChange={mockOnRichValueChange}
portalOrigin="mock-origin"
/>
);
rerender(
<UnThemedQueryField
theme={createTheme()}
query="my query"
syntaxLoaded
onRichValueChange={mockOnRichValueChange}
portalOrigin="mock-origin"
/>
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.instance().editor = { insertText: () => ({ deleteBackward: () => ({ value: 'fooo' }) }) };
wrapper.setProps({ syntaxLoaded: true });
expect(spyOnChange).toHaveBeenCalledWith('fooo', true);
expect(mockOnRichValueChange).toHaveBeenCalled();
});

it('should not re-render the editor if syntax is already loaded', () => {
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
const mockOnRichValueChange = jest.fn();
const { rerender } = render(
<UnThemedQueryField
theme={createTheme()}
query="my query"
onRichValueChange={mockOnRichValueChange}
syntaxLoaded
portalOrigin="mock-origin"
/>
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.setProps({ syntaxLoaded: true });
wrapper.instance().editor = {};
wrapper.setProps({ syntaxLoaded: true });
expect(spyOnChange).not.toBeCalled();
});
it('should not re-render the editor if editor itself is not defined', () => {
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
rerender(
<UnThemedQueryField
theme={createTheme()}
query="my query"
onRichValueChange={mockOnRichValueChange}
syntaxLoaded
portalOrigin="mock-origin"
/>
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.setProps({ syntaxLoaded: true });
expect(wrapper.instance().editor).toBeFalsy();
expect(spyOnChange).not.toBeCalled();
expect(mockOnRichValueChange).not.toBeCalled();
});

it('should not re-render the editor twice once syntax is fully loaded', () => {
const wrapper: any = shallow(
<UnThemedQueryField theme={createTheme()} query="my query" portalOrigin="mock-origin" />
const mockOnRichValueChange = jest.fn();
const { rerender } = render(
<UnThemedQueryField
theme={createTheme()}
onRichValueChange={mockOnRichValueChange}
query="my query"
portalOrigin="mock-origin"
/>
);
rerender(
<UnThemedQueryField
theme={createTheme()}
syntaxLoaded
onRichValueChange={mockOnRichValueChange}
query="my query"
portalOrigin="mock-origin"
/>
);
rerender(
<UnThemedQueryField
theme={createTheme()}
syntaxLoaded
onRichValueChange={mockOnRichValueChange}
query="my query"
portalOrigin="mock-origin"
/>
);
const spyOnChange = jest.spyOn(wrapper.instance(), 'onChange').mockImplementation(jest.fn());
wrapper.instance().editor = { insertText: () => ({ deleteBackward: () => ({ value: 'fooo' }) }) };
wrapper.setProps({ syntaxLoaded: true });
wrapper.setProps({ syntaxLoaded: true });
expect(spyOnChange).toBeCalledTimes(1);
expect(mockOnRichValueChange).toBeCalledTimes(1);
});
});
});
2 changes: 0 additions & 2 deletions packages/jaeger-ui-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
"@testing-library/react": "12.1.4",
"@testing-library/user-event": "14.4.3",
"@types/deep-freeze": "^0.1.1",
"@types/enzyme": "3.10.12",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/jest": "29.2.3",
"@types/lodash": "4.14.187",
Expand All @@ -25,7 +24,6 @@
"@types/slate-react": "0.22.9",
"@types/testing-library__jest-dom": "5.14.5",
"@types/tinycolor2": "1.4.3",
"enzyme": "3.11.0",
"sinon": "14.0.1",
"typescript": "4.8.4"
},
Expand Down
4 changes: 0 additions & 4 deletions public/test/jest-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// angular is imported.
import './global-jquery-shim';

import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import angular from 'angular';
import { configure } from 'enzyme';

import { EventBusSrv } from '@grafana/data';
import { GrafanaBootConfig } from '@grafana/runtime';
Expand Down Expand Up @@ -67,8 +65,6 @@ jest.mock('../app/core/core', () => ({
jest.mock('../app/angular/partials', () => ({}));
jest.mock('../app/features/plugins/plugin_loader', () => ({}));

configure({ adapter: new Adapter() });

const localStorageMock = (() => {
let store: any = {};
return {
Expand Down
Loading

0 comments on commit 92a750a

Please sign in to comment.