Skip to content

Commit

Permalink
chore: migrate to jest 29 (microsoft#27935)
Browse files Browse the repository at this point in the history
* chore: migrate to jest 29

* chore: apply legacy snapshot format to maintain same output for jest 29

* test(utilities): make Async test pass after jest 29 bump

* fix(scripts-jest): update ts-jest configuration introduce in v29

* test(react-portal): fix test and mitigate usage of problematic toMatchObject jest matcher used for DOM testing

* test(react): fix tests within ColorPicker caused by jest.fn cleanup changes introduced in new jest

* test(react-northstar): fix tests that have issues with jest.mock and jest.fn not being called properly
  • Loading branch information
Hotell authored Jun 2, 2023
1 parent 386ee70 commit b5a2f94
Show file tree
Hide file tree
Showing 12 changed files with 841 additions and 297 deletions.
5 changes: 5 additions & 0 deletions jest.preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ const baseConfig = {
cacheDirectory: '<rootDir>/node_modules/.cache/jest',
clearMocks: true,
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
// OLD format for migration to jest 29 - TODO: migrate to new format . https://jestjs.io/blog/2022/04/25/jest-28#future
snapshotFormat: {
escapeString: true,
printBasicPrototype: true,
},
};

module.exports = { ...baseConfig };
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"@griffel/react": "^1.5.7",
"@griffel/webpack-extraction-plugin": "0.3.11",
"@griffel/webpack-loader": "2.1.13",
"@jest/reporters": "28.1.3",
"@jest/reporters": "29.5.0",
"@mdx-js/loader": "1.6.22",
"@microsoft/api-extractor": "7.22.2",
"@microsoft/api-extractor-model": "7.17.1",
Expand Down Expand Up @@ -156,7 +156,7 @@
"@types/gulp-remember": "0.0.31",
"@types/gulp-sourcemaps": "0.0.35",
"@types/gulp-util": "3.0.36",
"@types/jest": "28.1.8",
"@types/jest": "29.5.1",
"@types/jest-axe": "3.5.5",
"@types/jju": "1.4.1",
"@types/json-schema": "^7.0.8",
Expand Down Expand Up @@ -194,7 +194,7 @@
"@wojtekmaj/enzyme-adapter-react-17": "0.6.7",
"ajv": "8.4.0",
"autoprefixer": "10.2.1",
"babel-jest": "28.1.3",
"babel-jest": "29.5.0",
"babel-loader": "8.2.2",
"babel-plugin-annotate-pure-calls": "0.4.0",
"babel-plugin-annotate-pure-imports": "1.0.0-1",
Expand Down Expand Up @@ -261,13 +261,13 @@
"html-webpack-plugin": "5.1.0",
"ignore-not-found-export-webpack-plugin": "1.0.2",
"imports-loader": "1.2.0",
"jest": "28.1.3",
"jest": "29.5.0",
"jest-axe": "6.0.1",
"jest-cli": "28.1.3",
"jest-environment-jsdom": "28.1.3",
"jest-environment-node-single-context": "28.1.0",
"jest-snapshot": "28.1.3",
"jest-watch-typeahead": "1.1.0",
"jest-cli": "29.5.0",
"jest-environment-jsdom": "29.5.0",
"jest-environment-node-single-context": "29.1.0",
"jest-snapshot": "29.5.0",
"jest-watch-typeahead": "2.2.2",
"jju": "1.4.0",
"json-schema": "0.4.0",
"json-stable-stringify-without-jsonify": "1.0.1",
Expand Down Expand Up @@ -338,7 +338,7 @@
"terser-webpack-plugin": "5.3.9",
"through2": "4.0.2",
"tmp": "0.2.1",
"ts-jest": "28.0.8",
"ts-jest": "29.1.0",
"ts-loader": "9.3.1",
"ts-node": "10.9.1",
"tsconfig-paths": "4.1.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
import * as React from 'react';

import { LikeIcon } from '@fluentui/react-icons-northstar';

import { handlesAccessibility, implementsShorthandProp, isConformant } from 'test/specs/commonTests';
import { mountWithProvider, EmptyThemeProvider } from 'test/utils';

import { ChatMessage } from 'src/components/Chat/ChatMessage';
import { Text } from 'src/components/Text/Text';
import { usePopper } from 'src/utils/positioner';
import { LikeIcon } from '@fluentui/react-icons-northstar';
import { ChatMessageDetails } from 'src/components/Chat/ChatMessageDetails';
import { ChatMessageContent } from 'src/components/Chat/ChatMessageContent';
import { mountWithProvider, EmptyThemeProvider } from 'test/utils';

jest.mock('src/utils/positioner', () => {
const actualPositioner = jest.requireActual('src/utils/positioner');

return {
...actualPositioner,
usePopper: jest.fn().mockReturnValue(actualPositioner.usePopper),
};
});
import * as positionerApi from 'src/utils/positioner';

const chatMessageImplementsShorthandProp = implementsShorthandProp(ChatMessage);

Expand All @@ -39,8 +31,12 @@ describe('ChatMessage', () => {
handlesAccessibility(ChatMessage);
});

describe('rtl', () => {
beforeEach(() => jest.clearAllMocks());
describe.only('rtl', () => {
let usePopperSpy;
beforeEach(() => {
jest.clearAllMocks();
usePopperSpy = jest.spyOn(positionerApi, 'usePopper');
});

function render(wrappingComponent?: React.ComponentType) {
const actionMenu = {
Expand Down Expand Up @@ -70,15 +66,15 @@ describe('ChatMessage', () => {
const RTLProvider = props => <EmptyThemeProvider {...props} rtl={true} />;
render(RTLProvider);

expect(usePopper).toHaveBeenCalledTimes(1);
expect(usePopper).toHaveBeenCalledWith(expect.objectContaining({ rtl: true }));
expect(usePopperSpy).toHaveBeenCalledTimes(1);
expect(usePopperSpy).toHaveBeenCalledWith(expect.objectContaining({ rtl: true }));
});

it('should pass rtl parameter as undefined to usePopper in LTR', () => {
render();

expect(usePopper).toHaveBeenCalledTimes(1);
expect(usePopper).toHaveBeenCalledWith(expect.objectContaining({ rtl: undefined }));
expect(usePopperSpy).toHaveBeenCalledTimes(1);
expect(usePopperSpy).toHaveBeenCalledWith(expect.objectContaining({ rtl: undefined }));
});
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { ProviderContextInput } from '@fluentui/react-bindings';
import type { CreateRenderer } from '@fluentui/react-northstar-styles-renderer';
import { mergeProviderContexts, mergePerformanceOptions, getRenderer } from 'src/utils/mergeProviderContexts';

describe('getRenderer', () => {
const createRenderer = jest.fn().mockImplementation(target => ({ target }));
const createRenderer = (target => {
return { target };
}) as unknown as CreateRenderer;

test(`without "target" defaults to a document`, () => {
// will be "undefined" as we call createRenderer() with "undefined"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,26 @@ describe('toMountNodeProps', () => {
it('handles HTMLElement', () => {
const element = document.createElement('div');

expect(toMountNodeProps(element)).toMatchObject({
element,
});
expect(toMountNodeProps(element)).toEqual({ element });
});

it('handles "null"', () => {
expect(toMountNodeProps(null)).toMatchObject({
expect(toMountNodeProps(null)).toEqual({
element: null,
});
});

it('handles "undefined"', () => {
expect(toMountNodeProps(null)).toMatchObject({});
expect(toMountNodeProps(undefined)).toEqual({});
});

it('handles objects', () => {
const element = document.createElement('div');

expect(toMountNodeProps({ element })).toMatchObject({
expect(toMountNodeProps({ element })).toEqual({
element,
});
expect(toMountNodeProps({ element, className: 'foo' })).toMatchObject({
expect(toMountNodeProps({ element, className: 'foo' })).toEqual({
element,
className: 'foo',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('setVirtualParent', () => {
setVirtualParent(child, virtualParent);

// Assert
expect(child).toMatchObject({ _virtual: { parent: virtualParent } });
expect(child).toEqual(expect.objectContaining({ _virtual: { parent: virtualParent } }));
});

it('should remove virtual parent when parent is undefined', () => {
Expand All @@ -21,6 +21,6 @@ describe('setVirtualParent', () => {
setVirtualParent(child);

// Assert
expect(child).toMatchObject({ _virtual: { parent: undefined } });
expect(child).toEqual(expect.objectContaining({ _virtual: { parent: undefined } }));
});
});
27 changes: 14 additions & 13 deletions packages/react/src/components/ColorPicker/ColorPicker.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,26 @@ const white = getColorFromString('#ffffff')!;
const AEAEAE = getColorFromString('#AEAEAE')!;

describe('ColorPicker', () => {
beforeEach(() => {
// Resetting ids to create predictability in generated ids.
resetIds();
});

let colorPicker: ColorPickerBase | null = null;
const colorPickerRef = (ref: ColorPickerBase | null) => {
colorPicker = ref;
};

let updatedColor: IColor | undefined;
const onChange = jest.fn((ev: any, color: IColor) => {
updatedColor = color;
let onChange: jest.Mock<void, [_ev: any, color: IColor], any>;

beforeEach(() => {
// Resetting ids to create predictability in generated ids.
resetIds();
onChange = jest.fn((_ev: any, color: IColor) => {
updatedColor = color;
});
});

afterEach(() => {
updatedColor = undefined;
// clear onChange calls
onChange.mockClear();
});

interface IValidateChangeOptions {
Expand Down Expand Up @@ -69,12 +76,6 @@ describe('ColorPicker', () => {
}
}

afterEach(() => {
updatedColor = undefined;
// clear onChange calls
onChange.mockClear();
});

it('renders correctly', () => {
const { container } = render(<ColorPicker color="#abcdef" />);
expect(container).toMatchSnapshot();
Expand Down
9 changes: 5 additions & 4 deletions packages/utilities/src/Async.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ describe('Async', () => {
// Increase count by a specific number, to test the arguments
// of the debounced function;
let callCount = 0;
const fn = jest.fn((increaseCount: number) => {
const fnMock = (increaseCount: number) => {
callCount += increaseCount;
return callCount;
});

};
let fn: jest.Mock<number, [increaseCount: number], unknown>;
let async: Async;
let debouncedFn: ICancelable<typeof fn> & typeof fn;

beforeEach(() => {
jest.useFakeTimers();

fn = jest.fn(fnMock);
async = new Async();
debouncedFn = async.debounce(fn, 100);
});
Expand Down Expand Up @@ -103,6 +103,7 @@ describe('Async', () => {
expect(fn).toHaveBeenCalledTimes(1);

dateMock.mockRestore();
jest.useRealTimers();
});
});
});
5 changes: 5 additions & 0 deletions scripts/jest/src/jest.preset.v0.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ const createConfig = (/** @type {import('@jest/types').Config.InitialOptions} */
}),
...customConfig.moduleNameMapper,
},
// OLD format for migration to jest 29 - TODO: migrate to new format . https://jestjs.io/blog/2022/04/25/jest-28#future
snapshotFormat: {
escapeString: true,
printBasicPrototype: true,
},
});

module.exports = createConfig;
20 changes: 12 additions & 8 deletions scripts/jest/src/jest.preset.v8.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,13 @@ const createConfig = (customConfig = {}) => {
},

transform: {
'^.+\\.tsx?$': 'ts-jest',
'^.+\\.tsx?$': [
'ts-jest',
{
/** https://kulshekhar.github.io/ts-jest/docs/28.0/getting-started/options/isolatedModules */
isolatedModules: true,
},
],
},

transformIgnorePatterns: ['/node_modules/', '/lib-commonjs/', '\\.js$'],
Expand All @@ -68,13 +74,6 @@ const createConfig = (customConfig = {}) => {
path.resolve(packageRoot, 'node_modules'),
path.resolve(__dirname, '../node_modules'),
],

globals: {
'ts-jest': {
/** https://kulshekhar.github.io/ts-jest/docs/28.0/getting-started/options/isolatedModules */
isolatedModules: true,
},
},
testEnvironmentOptions: {
url: 'http://localhost',
},
Expand All @@ -83,6 +82,11 @@ const createConfig = (customConfig = {}) => {
clearMocks: true,

watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
// OLD format for migration to jest 29 - TODO: migrate to new format . https://jestjs.io/blog/2022/04/25/jest-28#future
snapshotFormat: {
escapeString: true,
printBasicPrototype: true,
},
};

return merge(defaultConfig, customConfig);
Expand Down
12 changes: 6 additions & 6 deletions scripts/jest/src/jest.preset.v8.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,6 @@ describe(`v8 preset`, () => {

expect(actual).toEqual(
expect.objectContaining({
globals: {
'ts-jest': {
isolatedModules: true,
},
},
moduleDirectories: [
'node_modules',
`${workspaceRoot}/scripts/jest/node_modules`,
Expand All @@ -33,7 +28,12 @@ describe(`v8 preset`, () => {
},
testEnvironment: 'jsdom',
transform: {
'^.+\\.tsx?$': 'ts-jest',
'^.+\\.tsx?$': [
'ts-jest',
{
isolatedModules: true,
},
],
},
restoreMocks: true,
clearMocks: true,
Expand Down
Loading

0 comments on commit b5a2f94

Please sign in to comment.