This repository was archived by the owner on Jan 14, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 231
fix(icon-button): upgrade to mdc-web v1.1 #792
Merged
moog16
merged 1 commit into
material-components:feat/mdcweb-typescript-update
from
unknown repository
Apr 2, 2019
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ import * as td from 'testdouble'; | |
import {shallow} from 'enzyme'; | ||
import {IconButtonBase as IconButton} from '../../../packages/icon-button/index'; | ||
import {coerceForTesting} from '../helpers/types'; | ||
import {MDCIconButtonToggleEventDetail} from '@material/icon-button/types'; | ||
|
||
suite('IconButton'); | ||
|
||
|
@@ -34,7 +35,7 @@ test('renders anchor tag when isLink is true', () => { | |
|
||
test('#foundation.handleClick gets called onClick', () => { | ||
const wrapper = shallow<IconButton<HTMLButtonElement>>(<IconButton />); | ||
wrapper.instance().foundation.handleClick = td.func(); | ||
wrapper.instance().foundation.handleClick = td.func<() => void>(); | ||
wrapper.simulate('click'); | ||
td.verify(wrapper.instance().foundation.handleClick(), {times: 1}); | ||
}); | ||
|
@@ -62,13 +63,13 @@ test('aria-pressed is set false if passed as prop but on className is not passed | |
test('#get.classes has a class added to state.classList', () => { | ||
const wrapper = shallow(<IconButton />); | ||
wrapper.setState({classList: new Set(['test-class'])}); | ||
wrapper.hasClass('test-class'); | ||
assert.isTrue(wrapper.hasClass('test-class')); | ||
}); | ||
|
||
test('#adapter.addClass adds a class to state.classList', () => { | ||
const wrapper = shallow<IconButton<HTMLButtonElement>>(<IconButton />); | ||
wrapper.instance().adapter.addClass('test-class'); | ||
wrapper.state().classList.has('test-class'); | ||
assert.isTrue(wrapper.state().classList.has('test-class')); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wow - these tests were basically useless...that's for fixing these. |
||
}); | ||
|
||
test('#adapter.removeClass removes a class to state.classList', () => { | ||
|
@@ -91,7 +92,14 @@ test('#adapter.hasClass returns false if element does not contains class', () => | |
|
||
test('#adapter.setAttr sets aria-pressed', () => { | ||
const wrapper = shallow<IconButton<HTMLButtonElement>>(<IconButton />); | ||
wrapper.instance().adapter.setAttr('aria-pressed', true); | ||
assert.isTrue(wrapper.state()['aria-pressed']); | ||
wrapper.instance().adapter.setAttr('aria-pressed', 'true'); | ||
assert.equal(wrapper.state('aria-pressed'), 'true'); | ||
}); | ||
|
||
test('#adapter.notifyChange calls props.handleChange', () => { | ||
const handleChange = td.func<(event: MDCIconButtonToggleEventDetail) => void>(); | ||
const wrapper = shallow<IconButton<HTMLButtonElement>>(<IconButton handleChange={handleChange} />); | ||
const event = {isOn: false}; | ||
wrapper.instance().adapter.notifyChange(event); | ||
td.verify(handleChange(event), {times: 1}); | ||
}); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is done because
hasClass
would otherwise return a false positive if it were called after this. This led to theisOn
property in the event argument fornotifyChange
always being true.This pattern seems to be used throughout this library and it is a little worrying as it goes against the first two points that react advises about for using state correctly: https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
However, from what I can tell, it needs to work this way in order for
hasClass
to behave correctly.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gotcha - ya it I realize that setState is async, and that it can become out of sync with hasClass. It does seem wrong that we are relying on changing state directly without calling setState. That is why we were calling
new Set()
to create a new instance.We could possibly make the call to
props.handleChange
call async, by calling it in the componentDidUpdate. We could use a boolean indicatingstate.classList
is updating (let's call itstate.classListIsUpdating
. WhennotifyChange
gets trigger, we could set another booleanstate.hasChangeOccured
. (hopefully you're following). The componentDidUpdate statement would look like:Just a thought as a fix for this. It definitely doesn't belong in this PR, but maybe we can open another issue to fix this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And we should actually be consistent in the removeClass and addClass methods...
Created an issue #793
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@moog16 thanks for the feedback and creating a new issue for this.