UNPKG

@instructure/ui-react-utils

Version:

A React utility library made by Instructure Inc.

237 lines (236 loc) • 11.2 kB
/* * 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(); }); }); });