Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

Uplift Terra to use React 16 #1194

Merged
merged 23 commits into from
Feb 9, 2018
Merged

Uplift Terra to use React 16 #1194

merged 23 commits into from
Feb 9, 2018

Conversation

JakeLaCombe
Copy link
Contributor

@JakeLaCombe JakeLaCombe commented Feb 1, 2018

Summary

The Pull Request you have all been waiting for! I was looking through the different packages, and here are the biggest non passive changes that affected us

  • React 16 removes [data-reactroot] from the React Element
  • Enzyme with react-16 does not work with rendering portals. Given our test coverage with nightwatch and wdio covered these cases, I opted just to remove the render tests.
  • The new datepicker opts to use popper instead of tether for it's implementation.
  • The focusable attribute on SVG nodes takes a string as opposed to a boolean for it's value.
  • For our portal usage, we can use the new api as opposed to the legacy one, as indicated by the new imports.
  • React 16 requires requestAnimationFrame, meaning we need to add the raf polyfill to work with legacy IE browsers.
  • HTML Attributes are more strict. If you had a boolean and it expects a string, it won't convert it

Deployment LInk: https://terra-core-deployed-pr-1194.herokuapp.com/

@bjankord bjankord temporarily deployed to terra-core-deployed-pr-1194 February 1, 2018 18:38 Inactive
@JakeLaCombe
Copy link
Contributor Author

I'll leave commentary on my code review changes so that it provides more context.

@@ -24,7 +24,7 @@ describe('Alert with no props', () => {

it('throws error on missing locale prop in Base', () => {
try {
shallow(<Alert />);
render(<Alert />);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

shallow doesn't pass a context to the component anymore, so we need to do a full render to test that condition.

@@ -48,13 +48,21 @@ class Base extends React.Component {

componentDidMount() {
if (this.props.locale !== undefined) {
i18nLoader(this.props.locale, this.setState, this);
try {
i18nLoader(this.props.locale, this.setState, this);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For React 16, it no longer renders the component if it errors out. https://reactjs.org/blog/2017/07/26/error-handling-in-react-16.html

We can use componentDidCatch, but it gets hard with this component, as we never defined what it should do in that case. We just let it error out previously, which no longer works for us as nothing will render. We can switch to the ErrorComponent when we have established what we would like to do when a locale isn't found.

@bjankord bjankord temporarily deployed to terra-core-deployed-pr-1194 February 1, 2018 18:44 Inactive
expect(wrapper.instance().props.fitStartAttributes).toEqual({ style: { maxWidth: '10px' } });
expect(wrapper.instance().props.fillAttributes).toEqual({ style: { maxWidth: '20px' } });
expect(wrapper.instance().props.fitEndAttributes).toEqual({ style: { maxWidth: '30px' } });
expect(wrapper).toMatchSnapshot();
Copy link
Contributor

Choose a reason for hiding this comment

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

Smart 👍

.popper-container {
position: absolute;
top: 0;
z-index: 2147483647;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is the intent to set this to a value so high, z-index values on other elements wouldn't be higher?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. It's the same z-index that tether originally set so that it's widgets would display on top.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's the same z-index

We should add an inline comment mentioning that

@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 1, 2018 18:54 Inactive
@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 1, 2018 19:00 Inactive
@@ -40,7 +40,7 @@ class DateTimeUtils {
}

static formatMomentDateTime(momentDate, format) {
return momentDate && momentDate.isValid() ? momentDate.format(format) : '';
return momentDate && momentDate.isValid() ? momentDate.format(format) : undefined;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change is needed to resolve the following error.

warning.js:33 Warning: Failed prop type: Invalid prop `selected` of type `string` supplied to `DatePicker`, expected `object`.

@@ -10,8 +10,3 @@ it('should mount an open modal', () => {
const modal = mount(<ModalExample />);
expect(modal).toMatchSnapshot();
});

it('should render an open modal', () => {
const modal = render(<ModalExample />);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

For those curious, this line produced the following error.

<--- Last few GCs --->

[42935:0x102801600]    25833 ms: Mark-sweep 1405.6 (1452.6) -> 1405.6 (1452.6) MB, 1810.7 / 0.0 ms  allocation failure GC in old space requested
[42935:0x102801600]    27430 ms: Mark-sweep 1405.6 (1452.6) -> 1405.6 (1440.6) MB, 1596.5 / 0.0 ms  last resort GC in old space requested
[42935:0x102801600]    29223 ms: Mark-sweep 1405.6 (1440.6) -> 1405.6 (1440.6) MB, 1792.8 / 0.0 ms  last resort GC in old space requested


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x123410ba5ee1 <JSObject>
    1: read [/Users/jl021230/Documents/PopulationHealth/terra/terra-core/node_modules/react-dom/cjs/react-dom-server.node.development.js:~2206] [pc=0x26d1330d7379](this=0x12341a902ef9 <ReactDOMServerRenderer map = 0x12342cf40529>,bytes=0x1234906829a9 <Number inf>)
    3: renderToStaticMarkup [/Users/jl021230/Documents/PopulationHealth/terra/terra-core/node_modules/react-dom/cjs/react-dom-server....

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 1: node::Abort() [/Users/jl021230/.nvm/versions/node/v8.9.2/bin/node]
 2: node::FatalException(v8::Isolate*, v8::Local<v8::Value>, v8::Local<v8::Message>) [/Users/jl021230/.nvm/versions/node/v8.9.2/bin/node]
 3: v8::internal::V8::FatalProcessOutOfMemory(char const*, bool) [/Users/jl021230/.nvm/versions/node/v8.9.2/bin/node]
 4: v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [/Users/jl021230/.nvm/versions/node/v8.9.2/bin/node]
 5: v8::internal::Runtime_AllocateInTargetSpace(int, v8::internal::Object**, v8::internal::Isolate*) [/Users/jl021230/.nvm/versions/node/v8.9.2/bin/node]
 6: 0x26d132f8463d
 7: 0x26d1330d7379

I posted on enzymes repo, but didn't get much luck in regards to a solution.


const TestContainer = ({ children }) => (
<div className={styles.app} style={{ overflow: 'auto' }}>
<div id="wdio-test-wrapper">
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will be our base component. Not though that we still have to have individual for some tests, as they want to display in an individual component inside the wrapper.

@@ -21,7 +21,6 @@ const CustomEventsConsumer = () => (
<EmbeddedContentConsumer
src="#/tests/embedded-content-consumer-tests/custom-events-provider"
eventHandlers={eventHandlers}
fill
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Did we have a reason for these props? I couldn't find any documentation on them, and I found leaving them off still resulted in passing tests, and visual regression didn't reveal any noticeable behavior.

@@ -34,15 +34,6 @@ it('should render a arrange with status and customProps', () => {
expect(wrapper).toMatchSnapshot();
});

// Prop Tests
it('should have all props including customProps set correctly', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test is covered by the test above. I would have switched this to a snapshot, but the tests on line 34 already does that for us.

@@ -76,6 +76,8 @@ class TabMenu extends React.Component {

wrapOnClick(child) {
return (event) => {
event.stopPropagation();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Essentially, when we click on a tab, the new bounding rectangle is bubbling the click up to the menu click as well, which keeps the menu bar open.

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this something you found with the wdio screenshots?? Or in other test instances?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I found it through the wdio screenshots, but then tested it in a browser and saw the same behavior.

});
describe('Extended', () => {
beforeEach(() => {
browser.url('/#/tests/tabs-tests/extended');
browser.setViewportSize(viewport);
browser.moveToObject('.tabContent');
});
Terra.should.matchScreenshot({ viewports });
Terra.should.beAccessible({ viewports });
Terra.should.matchScreenshot({ viewports: [viewport] });
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this should reduce test time. We are already looping through all the viewports at this test, so I don't see a large benefit in having our screenshot comparison match at all of them for every single viewport.

@@ -14,8 +14,6 @@ const TimeInputTests = () => (
<li><Link to="/tests/time-input-tests/twelve-hour-filled-morning">TimeInput - Twelve Hour Default Time Morning</Link></li>
<li><Link to="/tests/time-input-tests/twelve-hour-filled-evening">TimeInput - Twelve Hour Default Time Evening</Link></li>
<li><Link to="/tests/time-input-tests/twelve-hour-mobile">TimeInput - Twelve Hour Mobile</Link></li>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to combine all the tests into the same component due to race conditions. I noticed that sometimes, componentWillMount would render before componentWillUnmount of the previous component, meaning sometimes the fake mobile mode would be disabled. Thus, I kept it at one component on the same page to ensure this doesn't happen.

@@ -1,14 +1,4 @@
/* global browser, Terra, before */
const shouldTheme = (customProperties, selector) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice. Glad this is finally gone :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll get rid of the terra-form-radio on another pull request

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually that one is different and needs to stay for now. The toolkit implementation will apply each variable one at at time and take a screenshot for each change. To get the correct theming screenshots for form-radio, multiple variables need to change at one time due to the default being browser naive.

@terra-bot
Copy link

terra-bot commented Feb 1, 2018

Warnings
⚠️

❗ Big PR. Consider breaking this into smaller PRs if applicaple

Generated by 🚫 dangerJS

@@ -37,7 +37,7 @@ const propTypes = {
/**
* Focusable attribute. IE 10/11 are focusable without this attribute.
*/
focusable: PropTypes.bool,
focusable: PropTypes.string,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

focusable is actually a string node for SVGs (https://allyjs.io/tutorials/focusing-in-svg.html) and react was throwing prop type errors when we gave it a boolean instead of a string.

@@ -3,6 +3,8 @@ Changelog

Unreleased
----------
### Changed
* Update to React 16
Copy link
Contributor

@emilyrohrbough emilyrohrbough Feb 1, 2018

Choose a reason for hiding this comment

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

This needs update to reflect the prop type change.

@@ -3,6 +3,7 @@ Changelog

Unreleased
----------
* Update to React 16
Copy link
Contributor

Choose a reason for hiding this comment

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

Not needed

@@ -3,6 +3,7 @@ Changelog

Unreleased
----------
* Update to React 16
Copy link
Contributor

Choose a reason for hiding this comment

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

Not needed

@JakeLaCombe
Copy link
Contributor Author

JakeLaCombe commented Feb 1, 2018

terra-form-radio has it's own implementation of wdio, but to get this pull request moving, I left off that change to another future pull request. It will produce tons of snapshots, and to better test visual regression, I want to leave the snapshots as unchanged as possible (which they are right now 😄 )

@@ -15,26 +15,26 @@ describe('Tabs - Responsive', () => {
browser.setViewportSize(viewport);
browser.moveToObject('.tabContent');
});
Terra.should.matchScreenshot({ viewports });
Terra.should.beAccessible({ viewports });
Terra.should.matchScreenshot({ viewports: [viewport] });
Copy link
Contributor

Choose a reason for hiding this comment

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

You should be able reduce this to Terra.should.matchScreenshot();

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Removed it, and it works great!

799ad0e

@mmalaker
Copy link

mmalaker commented Feb 8, 2018

Found issue in RtL orientation, when you click on the calendar button for a date picker within a modal, the calendar does not display. I'm testing the rest of the site in RTL to see if there are any other bugs.

@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 03:43 Inactive
@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 04:29 Inactive
@mmalaker
Copy link

mmalaker commented Feb 9, 2018

Rechecked the RTL date picker issue and that is now resolved. No other issues found. Functional verification completed.

@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 15:19 Inactive
@bjankord bjankord temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 18:02 Inactive
@bjankord bjankord temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 19:29 Inactive
@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 21:22 Inactive
@JakeLaCombe JakeLaCombe temporarily deployed to terra-core-deployed-pr-1194 February 9, 2018 21:35 Inactive
@noahbenham
Copy link
Contributor

I know this is closed but we were running into similar heap memory issues with our project. If this continues happening for terra-core and wasn't isolated to that line you removed, here's what we did @JakeLaCombe.

Root cause was including babel-polyfill in our jestSetup.js. Removing that took our heap memory usage from ~1.5GB to ~125MB. It doesn't look like that's true for this repo though.

We diagnosed our issue with node --expose-gc ./node_modules/.bin/jest --runInBand --logHeapUsage. That might be useful in case this continues happening and wasn't caused by the line you removed.

dylanklohr pushed a commit that referenced this pull request Apr 23, 2018
* Uplift Terra to use React 16

* Fix DateTime Utils

* Revert date-time-picker test change

* Fix code of testing screenshots

* Fix changelogs

* Document need for large z-index

* Fix Popper Settings for Datepicker

* Fix wdio styles

* Clean Up Tests

* Clean Up Lint
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants