From f69db2ebe3523e85660e0404e7b03e443aa2a338 Mon Sep 17 00:00:00 2001 From: Andrii Kostenko Date: Wed, 27 Mar 2019 01:14:18 +0200 Subject: [PATCH] feat(switch): upgrade to mdc-web v1 (#757) --- package-lock.json | 85 +++++++++++++++++++++++++-------- package.json | 2 +- packages/switch/index.tsx | 18 +++---- packages/switch/package.json | 2 +- test/unit/switch/index.test.tsx | 33 ++++++++----- 5 files changed, 97 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 94d8f5a16..cae11489b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1405,35 +1405,78 @@ } }, "@material/switch": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/switch/-/switch-0.41.0.tgz", - "integrity": "sha512-8YTrn1oisUhp6DlB1XAPeFWVr5nD88jlq9FoTVQOtGaUxaEybQD0nrsYI7OwaVm4HvSnepd2zmMvbjXKbQX4XQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/switch/-/switch-1.0.1.tgz", + "integrity": "sha512-McSLQA+VQdNV+wT6pRLpvlXv7V2BLsUkyIuCog8+Cs0Gsi4Lgs17I6iqdzQi4tySAX+G7nl6vqdUem/udUJZmw==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/elevation": "^0.41.0", - "@material/ripple": "^0.41.0", - "@material/rtl": "^0.40.1", - "@material/selection-control": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/elevation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/ripple": "^1.0.1", + "@material/rtl": "^0.42.0", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" }, "dependencies": { - "@material/base": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/base/-/base-0.41.0.tgz", - "integrity": "sha512-tEyzwBRu3d1H120SfKsDVYZHcqT5lKohh/7cWKR93aAaPDkSvjpKJIjyu2yuSkjpDduVZGzVocYbOvhUKhhzXQ==", - "dev": true + "@material/animation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/animation/-/animation-1.0.0.tgz", + "integrity": "sha512-Ed5/vggn6ZhSJ87yn3ZS1d826VJNFz73jHF2bSsgRtHDoB8KCuOwQMfdgAgDa4lKDF6CDIPCKBZPKrs2ubehdw==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/dom": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/dom/-/dom-1.0.1.tgz", + "integrity": "sha512-7gb9Tk8YBn2fLEa5fJfvDexG0QxvRGDb8c6uZEhvK4bTd2ZHCfHg9KrO+smC6Trbn5jC+FsBvdRZBbMjtS/E4g==", + "dev": true, + "requires": { + "tslib": "^1.9.3" + } + }, + "@material/elevation": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/elevation/-/elevation-1.0.0.tgz", + "integrity": "sha512-TqmvEXmZDYLm2X5lEnjKCsZMDkCXpxFFxL22AfCAQB5L4d0gAS7vqDEE797y4Rp+BBKEcOP71mum1l56RI3NBQ==", + "dev": true, + "requires": { + "@material/animation": "^1.0.0", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0" + } }, "@material/ripple": { - "version": "0.41.0", - "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-0.41.0.tgz", - "integrity": "sha512-rxEUVWM4AByDlTCH0kkthZQmUuY6eeN0X6cOHBoioFN2vUDk0D0Nfzz/N9FF2AlAf8C2lDDLrTuqnJPVIn+NHA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@material/ripple/-/ripple-1.0.1.tgz", + "integrity": "sha512-aBigRoVMjIU2lLDq7TMocI2H2YFbO1hICs5FTdSRp4Yis/QFTrgaW32q8yuHdZI56j+b2BWIWapqA2xpSmCMXQ==", "dev": true, "requires": { - "@material/animation": "^0.41.0", - "@material/base": "^0.41.0", - "@material/theme": "^0.41.0" + "@material/animation": "^1.0.0", + "@material/base": "^1.0.0", + "@material/dom": "^1.0.1", + "@material/feature-targeting": "^0.44.1", + "@material/theme": "^1.0.0", + "tslib": "^1.9.3" + } + }, + "@material/rtl": { + "version": "0.42.0", + "resolved": "https://registry.npmjs.org/@material/rtl/-/rtl-0.42.0.tgz", + "integrity": "sha512-VrnrKJzhmspsN8WXHuxxBZ69yM5IwhCUqWr1t1eNfw3ZEvEj7i1g3P31HGowKThIN1dc1Wh4LE14rCISWCtv5w==", + "dev": true + }, + "@material/theme": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@material/theme/-/theme-1.0.0.tgz", + "integrity": "sha512-Bg/BQLU5MmCwtQ3DHcSs9DodZB8PTvuItv1wXrP54S/wBVwryIB5uMDmERhnItbNnAFbkKhlAuhn1asMmMzfkQ==", + "dev": true, + "requires": { + "@material/feature-targeting": "^0.44.1" } } } diff --git a/package.json b/package.json index 5df31c790..72376643d 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "@material/ripple": "^1.0.0", "@material/select": "^0.40.1", "@material/snackbar": "^1.0.0", - "@material/switch": "^0.41.0", + "@material/switch": "^1.0.0", "@material/tab": "^1.0.0", "@material/tab-bar": "^1.0.0", "@material/tab-indicator": "^1.0.0", diff --git a/packages/switch/index.tsx b/packages/switch/index.tsx index ba46f2c1b..b840c5cae 100644 --- a/packages/switch/index.tsx +++ b/packages/switch/index.tsx @@ -22,8 +22,8 @@ import * as React from 'react'; import classnames from 'classnames'; -// @ts-ignore no .d.ts file -import {MDCSwitchFoundation} from '@material/switch/dist/mdc.switch'; +import {MDCSwitchAdapter} from '@material/switch/adapter'; +import {MDCSwitchFoundation} from '@material/switch/foundation'; import ThumbUnderlay from './ThumbUnderlay'; import NativeControl from './NativeControl'; @@ -44,7 +44,7 @@ interface SwitchState { export default class Switch extends React.Component { rippleActivator: React.RefObject = React.createRef(); - foundation?: MDCSwitchFoundation; + foundation!: MDCSwitchFoundation; constructor(props: SwitchProps) { super(props); @@ -66,16 +66,16 @@ export default class Switch extends React.Component { componentDidMount() { this.foundation = new MDCSwitchFoundation(this.adapter); this.foundation.init(); - this.foundation.setChecked(this.props.checked); - this.foundation.setDisabled(this.props.disabled); + this.foundation.setChecked(this.props.checked!); + this.foundation.setDisabled(this.props.disabled!); } componentDidUpdate(prevProps: SwitchProps) { if (this.props.checked !== prevProps.checked) { - this.foundation.setChecked(this.props.checked); + this.foundation.setChecked(this.props.checked!); } if (this.props.disabled !== prevProps.disabled) { - this.foundation.setDisabled(this.props.disabled); + this.foundation.setDisabled(this.props.disabled!); } } @@ -89,7 +89,7 @@ export default class Switch extends React.Component { return classnames('mdc-switch', Array.from(classList), className); } - get adapter() { + get adapter(): MDCSwitchAdapter { return { addClass: (className: string) => { const {classList} = this.state; @@ -112,7 +112,7 @@ export default class Switch extends React.Component { onChange = (evt: React.ChangeEvent) => { this.setState({nativeControlChecked: evt.target.checked}); - this.foundation && this.foundation.handleChange(evt); + this.foundation && this.foundation.handleChange(evt.nativeEvent); }; render() { diff --git a/packages/switch/package.json b/packages/switch/package.json index 40d1d6d7c..f5f3a5194 100644 --- a/packages/switch/package.json +++ b/packages/switch/package.json @@ -17,7 +17,7 @@ }, "dependencies": { "@material/react-ripple": "^0.11.0", - "@material/switch": "^0.41.0", + "@material/switch": "^1.0.0", "classnames": "^2.2.6", "react": "^16.3.2" }, diff --git a/test/unit/switch/index.test.tsx b/test/unit/switch/index.test.tsx index 5bdf79a0a..bf846ab3b 100644 --- a/test/unit/switch/index.test.tsx +++ b/test/unit/switch/index.test.tsx @@ -3,9 +3,15 @@ import {assert} from 'chai'; import {shallow, mount} from 'enzyme'; import * as td from 'testdouble'; import Switch from '../../../packages/switch/index'; +import {coerceForTesting} from '../helpers/types'; suite('Switch'); +const getAdapter = (instance: Switch) => { + // @ts-ignore + return instance.foundation.adapter_; +}; + test('creates foundation', () => { const wrapper = shallow(); assert.exists(wrapper.instance().foundation); @@ -47,14 +53,14 @@ test('has checked class when props.checked is true', () => { test('#foundation.setChecked gets called when prop.checked updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setChecked = td.func(); + wrapper.instance().foundation.setChecked = td.func<(setChecked: boolean) => null>(); wrapper.setProps({checked: true}); td.verify(wrapper.instance().foundation.setChecked(true), {times: 1}); }); test('#foundation.setDisabled gets called when prop.disabled updates', () => { const wrapper = shallow(); - wrapper.instance().foundation.setDisabled = td.func(); + wrapper.instance().foundation.setDisabled = td.func<(disabled: boolean) => null>(); wrapper.setProps({disabled: true}); td.verify(wrapper.instance().foundation.setDisabled(true), {times: 1}); }); @@ -62,27 +68,27 @@ test('#foundation.setDisabled gets called when prop.disabled updates', () => { test('#componentWillUnmount destroys foundation', () => { const wrapper = shallow(); const foundation = wrapper.instance().foundation; - foundation.destroy = td.func(); + foundation.destroy = td.func<() => null>(); wrapper.unmount(); td.verify(foundation.destroy(), {times: 1}); }); test('#adapter.addClass adds class to state.classList', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.addClass('test-class-name'); + getAdapter(wrapper.instance()).addClass('test-class-name'); assert.isTrue(wrapper.state().classList.has('test-class-name')); }); test('#adapter.removeClass removes class from state.classList', () => { const wrapper = shallow(); wrapper.setState({classList: new Set(['test-class-name'])}); - wrapper.instance().foundation.adapter_.removeClass('test-class-name'); + getAdapter(wrapper.instance()).removeClass('test-class-name'); assert.isFalse(wrapper.state().classList.has('test-class-name')); }); test('#adapter.setNativeControlChecked updates state.nativeControlChecked', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.setNativeControlChecked(true); + getAdapter(wrapper.instance()).setNativeControlChecked(true); assert.isTrue(wrapper.state().nativeControlChecked); }); @@ -94,7 +100,7 @@ test('#state.nativeControlChecked updates NativeControl', () => { test('#adapter.setNativeControlDisabled updates state.nativeControlDisabled', () => { const wrapper = shallow(); - wrapper.instance().foundation.adapter_.setNativeControlDisabled(true); + getAdapter(wrapper.instance()).setNativeControlDisabled(true); assert.isTrue(wrapper.state().nativeControlDisabled); }); @@ -116,12 +122,17 @@ test('calls foundation.handleChange in NativeControl props.onChange', () => { const onChange = td.func() as React.ChangeEventHandler; const wrapper = mount(); const nativeControl = wrapper.find('.mdc-switch__native-control'); - const mockEvt = { + const mockEvt = coerceForTesting>({ target: { checked: true, }, - } as React.ChangeEvent; - wrapper.instance().foundation.handleChange = td.func(); + nativeEvent: { + target: { + checked: true, + }, + }, + }); + wrapper.instance().foundation.handleChange = td.func<(evt: Event) => null>(); nativeControl.props().onChange!(mockEvt); - td.verify(wrapper.instance().foundation.handleChange(mockEvt), {times: 1}); + td.verify(wrapper.instance().foundation.handleChange(mockEvt.nativeEvent), {times: 1}); });