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

ShowMoreCard should expand if updated content changes #3057

Merged
merged 1 commit into from
Sep 4, 2017
Merged

ShowMoreCard should expand if updated content changes #3057

merged 1 commit into from
Sep 4, 2017

Conversation

willdurand
Copy link
Member

Fix mozilla/addons#10709


This PR fixes an issue when the description of an add-on has a smaller size than the previously browsed one.

Gif

2017-09-01 12 42 33

Copy link
Contributor

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

r+wc

Looks good, if moving away from ReactDOM in that component would be easy that'd be great, but if not no worries.

it('expands if new child content is smaller', () => {
const root = mount(
<ShowMoreCardBase i18n={getFakeI18nInst()}>
This should be a very long content, but we cannot get `clientHeight` in
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick but this would be better written as "This would be very long content, but [...]"

@@ -29,15 +29,13 @@ export class ShowMoreCardBase extends React.Component {
}

componentWillReceiveProps() {
this.truncateToMaxHeight(ReactDOM.findDOMNode(this.contents));
this.setState({ expanded: true }, () => {
this.truncateToMaxHeight(ReactDOM.findDOMNode(this.contents));
Copy link
Contributor

Choose a reason for hiding this comment

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

While we're here, should we still be using ReactDOM.findDOMNode? I forget if we can do this with refs or not but maybe we could?

@codecov-io
Copy link

codecov-io commented Sep 1, 2017

Codecov Report

Merging #3057 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    mozilla/addons-frontend#3057   +/-   ##
=======================================
  Coverage   95.05%   95.05%           
=======================================
  Files         152      152           
  Lines        2792     2792           
  Branches      543      543           
=======================================
  Hits         2654     2654           
  Misses        119      119           
  Partials       19       19
Impacted Files Coverage Δ
src/ui/components/ShowMoreCard/index.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 65b08aa...6d03032. Read the comment docs.

@willdurand
Copy link
Member Author

@tofumatt thanks for the review, just addressed your comments.

Copy link
Contributor

@tofumatt tofumatt left a comment

Choose a reason for hiding this comment

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

Just tested locally: works great. Thanks for removing the findDOMNode call; I think that one was my fault 😅

it('expands if new child content is smaller', () => {
const root = mount(
<ShowMoreCardBase i18n={getFakeI18nInst()}>
This would be a very long content, but we cannot get `clientHeight` in
Copy link
Contributor

Choose a reason for hiding this comment

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

Nitpick: should be "This would be very long content" not "a very long content"

Copy link
Member Author

Choose a reason for hiding this comment

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

doh 😅

@willdurand willdurand merged commit aa4561f into mozilla:master Sep 4, 2017
@willdurand willdurand deleted the fix-3026 branch September 4, 2017 10:44
Copy link
Contributor

@kumar303 kumar303 left a comment

Choose a reason for hiding this comment

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

I know you already merged this but I think it could use a fix-up. Be careful with setState() callbacks since they are asynchronous.

@@ -29,15 +28,13 @@ export class ShowMoreCardBase extends React.Component {
}

componentWillReceiveProps() {
this.truncateToMaxHeight(ReactDOM.findDOMNode(this.contents));
this.setState({ expanded: true }, () => {
this.truncateToMaxHeight(this.contents);
Copy link
Contributor

Choose a reason for hiding this comment

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

This will work in production but I don't think it will work for our test suite. The problem is that React does not guarantee that the callback to setState() will be invoked immediately. Thus, the test you wrote will probably pass most of the time but not all of the time. If the setState() callback is delayed then your test will fail.

There are a few ways to solve this. We could try to wedge promises in here so that the test can use a promise chain. I don't see an easy way to do that.

Alternatively, we could keep the process synchronous which would make the test you already wrote pass 100% of the time. I think restoring componentWillReceiveProps() to how it was and adding this else block would accomplish that:

truncateToMaxHeight = (contents) => {
  // If the contents are short enough they don't need a "show more" link; the
  // contents are expanded by default.
  if (contents.clientHeight > MAX_HEIGHT) {
    this.setState({ expanded: false });
  } else {
    this.setState({ expanded: true });
  }
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, it's possible that Enzyme has some trickery to ensure all batched state changes are applied but they don't document this. I'm skeptical since this kind of state change is triggered from within the component (not from an Enzyme method).

Copy link
Member Author

@willdurand willdurand Sep 5, 2017

Choose a reason for hiding this comment

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

What we could do (maybe) is reusing the callback from Enzyme setState() (see: enzymejs/enzyme#617) and ensure the test case asserts things once the setState() has been triggered (and use done() to ensure the test does not silently fail). WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh, yeah, we really can't rely on setState() being synchronous anywhere. enzymejs/enzyme#509 (comment)

It would be nice to use promises instead of done() but your approach will work. Creating a promise wrapper for everywhere we rely on wrapper.setState() in the tests is probably a better long term solution.

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

Successfully merging this pull request may close these issues.

Short description has "Read More" link
4 participants