Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Checkbox): prevent click propagation from the input element #3435

Merged
merged 10 commits into from
Feb 21, 2019

Conversation

Fabianopb
Copy link
Member

@Fabianopb Fabianopb commented Feb 13, 2019

Initially the click was being fired from both label and input
checkbox-antes

Now it only comes from label
checkbox-depois

(Closes #3433)
(Closes #3440)

@codecov-io
Copy link

codecov-io commented Feb 13, 2019

Codecov Report

Merging #3435 into master will increase coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3435      +/-   ##
==========================================
+ Coverage   99.89%   99.89%   +<.01%     
==========================================
  Files         172      172              
  Lines        2820     2830      +10     
==========================================
+ Hits         2817     2827      +10     
  Misses          3        3
Impacted Files Coverage Δ
src/modules/Checkbox/Checkbox.js 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5c7766f...96211aa. Read the comment docs.

@layershifter
Copy link
Member

Actually we should check:

  • only one click was propagated with id on label
  • only one click was propagated with id on input
  • only one click was propagated without id on input
  • only one click was propagated without id on label

@Fabianopb
Copy link
Member Author

I can check that later, but just to confirm, the id goes directly on the Checkbox, right? And then it's passed to the input and label within the component.

So if we're testing

mount(
  <div role='presentation' onClick={onClick}>
    <Checkbox id='foo' />
  </div>,
)

We could also test

mount(
  <div role='presentation' onClick={onClick}>
    <Checkbox />
  </div>,
)

Then it's all or nothing with the id, right?

@layershifter
Copy link
Member

the id goes directly on the Checkbox, right?

Absolutely

const wrapperWithId = mount(
  <div role='presentation' onClick={onClick}>
    <Checkbox id='foo' />
  </div>,
)
const wrapper = mount(
  <div role='presentation' onClick={onClick}>
    <Checkbox />
  </div>,
)

wrapperWithId.find('input').click() // 1
wrapperWithId.find('label').click() // 2
wrapper.find('input').click() // 3
wrapper.find('label').click() // 4

@Fabianopb
Copy link
Member Author

Oh that's right, we set the id in the Checkbox, but then we can simulate the click both on the input and on the label. I'll check that later!

@Fabianopb
Copy link
Member Author

Fabianopb commented Feb 13, 2019

Tests updated @layershifter !
inputs don't propagate click because there's always a label on top of them, so the click event is always propagated from label.

</div>,
)
const target = document.querySelector(`.ui.checkbox ${assertion.target}`)
domEvent.click(target)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-const target = document.querySelector(`.ui.checkbox ${assertion.target}`)
-domEvent.click(target)
+domEvent.click(`.ui.checkbox ${assertion.target}`)

This should be a valid change 😺 

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know!

const target = document.querySelector(`.ui.checkbox ${assertion.target}`)
domEvent.click(target)
if (assertion.propagates) onClick.should.have.been.calledOnce()
else onClick.should.not.have.been.called()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-if (assertion.propagates) onClick.should.have.been.calledOnce()
-else onClick.should.not.have.been.called()
+onClick.should.have.callCount(Number(assertion.propagates))

We can test the call count directly, https://github.com/domenic/sinon-chai

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea!

@@ -201,6 +201,50 @@ describe('Checkbox', () => {
})
})

describe('click propagation', () => {
const assertions = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const assertions = [
const assertMatrix= [

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll change that

@@ -258,6 +258,7 @@ export default class Checkbox extends Component {
tabIndex={this.computeTabIndex()}
type={type}
value={value}
onClick={e => e.stopPropagation()}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we create a handleInputClick method and make a comment there with a link to the matching issue?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And sort props in alphabetic order ❤️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@layershifter layershifter changed the title Checkbox: Prevents click propagation from the input fix(Checkbox): prevent click propagation from the input element Feb 14, 2019
@layershifter
Copy link
Member

@Fabianopb I made some comments, can you please address them? Nice job 👍

@Fabianopb
Copy link
Member Author

Awesome @layershifter thanks for the comments, I'll try address them later today!

Copy link
Member Author

@Fabianopb Fabianopb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@layershifter I just pushed the changes!

@@ -258,6 +258,7 @@ export default class Checkbox extends Component {
tabIndex={this.computeTabIndex()}
type={type}
value={value}
onClick={e => e.stopPropagation()}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@@ -201,6 +201,50 @@ describe('Checkbox', () => {
})
})

describe('click propagation', () => {
const assertions = [
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I'll change that

</div>,
)
const target = document.querySelector(`.ui.checkbox ${assertion.target}`)
domEvent.click(target)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know!

const target = document.querySelector(`.ui.checkbox ${assertion.target}`)
domEvent.click(target)
if (assertion.propagates) onClick.should.have.been.calledOnce()
else onClick.should.not.have.been.called()
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea!

@layershifter
Copy link
Member

@Fabianopb I added changes that I picked from @levithomason branch 😸 Can you please help to test these changes? Did I miss something? I.e. double clicks, event propagation, right mouse click?

Copy link
Member Author

@Fabianopb Fabianopb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@layershifter that looks good to me, just one detail I got from re-testing the behavior manually:

  • without "id" the parent listens for a click coming necessarily from the label
  • with "id" the parent listens for a click coming necessarily from the input

Is that ok/intended?

events: {
label: ['mouseup', 'click'],
input: ['click'],
},
target: 'label',
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This target property doesn't seem to be used anymore, is that so?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch 👍

@layershifter
Copy link
Member

Is that ok/intended?

For me it looks fine, I don't see a big issue. I've tested it again, works like a charm 💎

Thank you!

@levithomason
Copy link
Member

@Fabianopb You've contributed here before and you've shown care and initiative for ensuring SUIR becomes better. We appreciate this and want to enable you to do more. I've added you as a collaborator. You're now able to manage issues and PRs as well as create branches here in the main repo. You no longer need to work from a fork. Merging to master is the only reserved permission.

We are very select about who we add and when, so know that we trust your abilities and your judgment. Please feel free to weigh in on any issues and PRs that you have an opinion about. You have a share of ownership and say here now.

Once you accept the invite (see your email), you might want to show the Semantic Org badge publicly on your profile. To do that, navigate to the "people" page and change the "private" dropdown to "public" for your user in the table. Here's a direct link to your user in the table.

/cc
@Semantic-Org/react-collaborators
@Semantic-Org/react-maintainers

Please welcome @Fabianopb to our ranks 😄 🎉

@levithomason
Copy link
Member

Released in semantic-ui-react@0.86.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants