@instructure/ui-react-utils
Version:
A React utility library made by Instructure Inc.
237 lines (236 loc) • 11.2 kB
JavaScript
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 - present Instructure, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import { Component } from 'react';
import { vi } from 'vitest';
import PropTypes from 'prop-types';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom';
import { deprecated } from '../deprecated';
import { jsxs as _jsxs, jsx as _jsx } from "@emotion/react/jsx-runtime";
class TestComponent extends Component {
render() {
return _jsxs("div", {
children: [this.props.qux, " ", this.props.bar]
});
}
}
TestComponent.displayName = "TestComponent";
TestComponent.propTypes = {
bar: PropTypes.string,
qux: PropTypes.string
};
TestComponent.defaultProps = {
bar: null,
qux: 'Hello'
};
describe('@deprecated', () => {
describe('deprecated props', () => {
var _DeprecatedComponent, _DeprecatedComponent2, _DeprecatedComponent3;
const DeprecatedComponent = deprecated('2.1.0', {
foo: 'bar',
baz: true
})(TestComponent);
it('should warn when suggesting new prop when using old prop', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
render(_DeprecatedComponent || (_DeprecatedComponent = _jsx(DeprecatedComponent, {
foo: "Jane"
})));
const expectedWarningMessage = 'Warning: [TestComponent] `foo` is deprecated and will be removed in version 2.1.0. Use `bar` instead. ';
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
it('should warn when using old prop with no new prop', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
render(_DeprecatedComponent2 || (_DeprecatedComponent2 = _jsx(DeprecatedComponent, {
baz: "Goodbye"
})));
const expectedWarningMessage = 'Warning: [TestComponent] `baz` is deprecated and will be removed in version 2.1.0.';
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
it('should not output a warning using new prop', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
render(_DeprecatedComponent3 || (_DeprecatedComponent3 = _jsx(DeprecatedComponent, {
bar: "Jane"
})));
expect(consoleWarningSpy).not.toHaveBeenCalled();
consoleWarningSpy.mockRestore();
});
});
describe('deprecated component', () => {
var _DeprecatedComponent4;
const DeprecatedComponent = deprecated('3.4.0')(TestComponent);
it('should warn that the entire component is deprecated if no old props are supplied', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
render(_DeprecatedComponent4 || (_DeprecatedComponent4 = _jsx(DeprecatedComponent, {})));
const expectedWarningMessage = 'Warning: [TestComponent] is deprecated and will be removed in version 3.4.0.';
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
});
describe('deprecated component with a changed package message', () => {
var _DeprecatedComponent5;
const DeprecatedComponent = deprecated('5.0.0', null, deprecated.changedPackageWarning('ui-forms', 'ui-number-input'))(TestComponent);
it('should warn that the component is deprecated and output a warning that the package changed', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const expectedWarningMessage = 'Warning: [TestComponent] is deprecated and will be removed in version 5.0.0. It has been moved from @instructure/ui-forms to @instructure/ui-number-input.';
render(_DeprecatedComponent5 || (_DeprecatedComponent5 = _jsx(DeprecatedComponent, {})));
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
});
describe('component with deprecated prop values', () => {
it('should not warn when an allowed prop value is supplied', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
class DeprecatedPropValueComponent extends Component {
render() {
return _jsx("div", {
children: this.props.color
});
}
}
DeprecatedPropValueComponent.displayName = "DeprecatedPropValueComponent";
DeprecatedPropValueComponent.propTypes = {
color: deprecated.deprecatePropValues(PropTypes.oneOf(['red', 'yellow', 'blue', 'orange', 'gold']), ['blue', 'orange', 'gold'])
};
DeprecatedPropValueComponent.defaultProps = {
color: 'red'
};
render(_jsx(DeprecatedPropValueComponent, {
color: "yellow"
}));
expect(consoleWarningSpy).not.toHaveBeenCalled();
consoleWarningSpy.mockRestore();
});
it('should warn when a forbidden prop value is supplied', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const color = 'orange';
class DeprecatedPropValueComponent extends Component {
render() {
return _jsx("div", {
children: this.props.color
});
}
}
DeprecatedPropValueComponent.displayName = "DeprecatedPropValueComponent";
DeprecatedPropValueComponent.propTypes = {
color: deprecated.deprecatePropValues(PropTypes.oneOf(['red', 'yellow', 'blue', 'orange', 'gold']), ['blue', 'orange', 'gold'])
};
DeprecatedPropValueComponent.defaultProps = {
color: 'red'
};
render(_jsx(DeprecatedPropValueComponent, {
color: color
}));
const expectedWarningMessage = `The '${color}' value for the \`color\` prop is deprecated.`;
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
it('should warn with additional message text when a forbidden prop value is supplied and has message text', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const color = 'gold';
const message = 'It will be removed in v8.0.0.';
class DeprecatedPropValueComponent extends Component {
render() {
return _jsx("div", {
children: this.props.color
});
}
}
DeprecatedPropValueComponent.displayName = "DeprecatedPropValueComponent";
DeprecatedPropValueComponent.propTypes = {
color: deprecated.deprecatePropValues(PropTypes.oneOf(['red', 'yellow', 'blue', 'orange', 'gold']), ['blue', 'orange', 'gold'], 'It will be removed in v8.0.0.')
};
DeprecatedPropValueComponent.defaultProps = {
color: 'red'
};
render(_jsx(DeprecatedPropValueComponent, {
color: color
}));
const expectedWarningMessage = `The '${color}' value for the \`color\` prop is deprecated. ${message}`;
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
it('should call functional message with the correct props', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const messageMock = vi.fn();
const color = 'gold';
class DeprecatedPropValueComponent extends Component {
render() {
return _jsx("div", {
children: this.props.color
});
}
}
DeprecatedPropValueComponent.displayName = "DeprecatedPropValueComponent";
DeprecatedPropValueComponent.propTypes = {
color: deprecated.deprecatePropValues(PropTypes.oneOf(['red', 'yellow', 'blue', 'orange', 'gold']), ['blue', 'orange', 'gold'], messageMock)
};
DeprecatedPropValueComponent.defaultProps = {
color: 'red'
};
render(_jsx(DeprecatedPropValueComponent, {
color: color
}));
const _messageMock$mock$cal = messageMock.mock.calls[0][0],
props = _messageMock$mock$cal.props,
propName = _messageMock$mock$cal.propName,
propValue = _messageMock$mock$cal.propValue;
expect(props).toEqual({
color
});
expect(propName).toBe('color');
expect(propValue).toBe(color);
expect(consoleWarningSpy).toHaveBeenCalled();
consoleWarningSpy.mockRestore();
});
it('should warn with a completely custom message when provided message is functional and prop value is forbidden', () => {
const consoleWarningSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
const color = 'gold';
class DeprecatedPropValueComponent extends Component {
render() {
return _jsx("div", {
children: this.props.color
});
}
}
DeprecatedPropValueComponent.displayName = "DeprecatedPropValueComponent";
DeprecatedPropValueComponent.propTypes = {
color: deprecated.deprecatePropValues(PropTypes.oneOf(['red', 'yellow', 'blue', 'orange', 'gold']), ['blue', 'orange', 'gold'], ({
propValue,
propName
}) => `The ${propValue} value for ${propName} has been deprecated. Use the FooBar component with the 'baz' prop set instead.`)
};
DeprecatedPropValueComponent.defaultProps = {
color: 'red'
};
render(_jsx(DeprecatedPropValueComponent, {
color: color
}));
const expectedWarningMessage = `The ${color} value for color has been deprecated. Use the FooBar component with the 'baz' prop set instead.`;
expect(consoleWarningSpy).toHaveBeenCalledWith(expect.stringContaining(expectedWarningMessage), expect.any(String));
consoleWarningSpy.mockRestore();
});
});
});