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

React 16 and Enzyme 3 migration #1885

Merged
merged 43 commits into from
Dec 13, 2017
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
817d141
Bump to react 16, regen lockfile
adidahiya Dec 11, 2017
4478ac8
pure-render-decorator -> React.PureComponent
adidahiya Dec 11, 2017
c5a98e4
Migrate to react-transition-group
adidahiya Dec 11, 2017
73d7a8e
Migrate to ReactDOM.createPortal
adidahiya Dec 11, 2017
3df77f1
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 11, 2017
49f8069
Fix Table component shouldComponentUpdate warnings
adidahiya Dec 11, 2017
c2074d5
Restore wrapper div for Portal component
adidahiya Dec 11, 2017
ab2c99b
Upgrade enzyme, install enzyme-adapter-react-16
adidahiya Dec 11, 2017
cee34d5
Configure isomorphic tests with enzyme adapter
adidahiya Dec 11, 2017
9efdfbf
Skip Portal isomorphic tests
adidahiya Dec 12, 2017
f2ec4e6
Load es6-shim in all tests
adidahiya Dec 12, 2017
d1c94a7
Fix NumericInput prop validation tests
adidahiya Dec 12, 2017
c7fa963
Add TestErrorBoundary component
adidahiya Dec 12, 2017
a1cc25a
Create @blueprintjs/test-commons package
adidahiya Dec 12, 2017
391fadb
Fix DatePicker prop validation tests
adidahiya Dec 12, 2017
4158d2e
Fix more prop validation tests
adidahiya Dec 12, 2017
6d90e49
Fix more prop validation tests
adidahiya Dec 12, 2017
ecfa923
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 12, 2017
307297b
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 12, 2017
02cbae9
Fix up test config for latest Enzyme; load CSS files
adidahiya Dec 12, 2017
3395389
Move tabs2 tests to their own folder
adidahiya Dec 12, 2017
ce4c03f
Skip more tests
adidahiya Dec 12, 2017
53d894d
[CollapsibleList] fix unit tests
adidahiya Dec 12, 2017
583507e
Add test:karma:debug NPM scripts to libraries
adidahiya Dec 12, 2017
2f5a61b
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 12, 2017
c30628f
Upgrade tsc in test-commons package
adidahiya Dec 12, 2017
9e94155
ReactWrapper#getNode() -> ReactWrapper#instance()
adidahiya Dec 12, 2017
b728ccb
Disable karma coverage in debug scripts
adidahiya Dec 12, 2017
b930727
Add two different abstract components, pure and not (#1896)
gscshoyru Dec 12, 2017
18cb414
Remove unused overlayTransition.tsx
adidahiya Dec 12, 2017
0b9ee4a
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 12, 2017
b4f5068
Fix semantic merge conflicts from select package moves
adidahiya Dec 12, 2017
e0238ad
Merge remote-tracking branch 'origin/ad/react-16' into ad/react-16
adidahiya Dec 12, 2017
7f62bdd
Merge remote-tracking branch 'origin/master' into ad/react-16
adidahiya Dec 13, 2017
bf7bfb3
Fix core tests (#1898)
giladgray Dec 13, 2017
9397fe8
Fix table tests (#1897)
themadcreator Dec 13, 2017
3f38773
React 16/Enzyme 3 - Fix datetime tests (#1899)
cmslewis Dec 13, 2017
d4299b8
Skip abstractComponent coverage; fix select package test setup
adidahiya Dec 13, 2017
6a49270
Address follow up comments on #1898
adidahiya Dec 13, 2017
022586c
Remove extraneous core karma test config
adidahiya Dec 13, 2017
5dbc249
Remove extra props interface in table impl
adidahiya Dec 13, 2017
aa47e76
Remove --browsers from test:karma:debug
adidahiya Dec 13, 2017
71988dd
Address CR feedback on tests
adidahiya Dec 13, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/tsconfig.base.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "2.4.2",
"version": "2.6.2",
"compilerOptions": {
"declaration": true,
"experimentalDecorators": true,
Expand Down
11 changes: 5 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,12 @@
"@types/chai": "^4.0.4",
"@types/classnames": "^2.2.3",
"@types/dom4": "^1.5.20",
"@types/enzyme": "^2.8.0",
"@types/enzyme": "^3.1.5",
"@types/enzyme-adapter-react-16": "^1.0.1",
"@types/mocha": "^2.2.43",
"@types/pure-render-decorator": "^0.2.28",
"@types/react": "^16.0.14",
"@types/react-addons-css-transition-group": "^15.0.3",
"@types/react-addons-transition-group": "^15.0.1",
"@types/react-dom": "^16.0.1",
"@types/react": "^16.0.28",
"@types/react-transition-group": "^2.0.6",
"@types/react-dom": "^16.0.3",
"@types/sinon": "^2.3.7",
"@types/tether": "^1.4.3",
"@types/webpack": "^3.8.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/core/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ module.exports = function (config) {
const baseConfig = createKarmaConfig({
dirname: __dirname,
coverageExcludes: [
// not worth full coverage
"src/accessibility/*",
"src/common/abstractComponent*",
// deprecated components
"src/components/popover/*",
Copy link
Contributor

Choose a reason for hiding this comment

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

are these actually deprecated if they're being replaced by labs components?

Copy link
Contributor Author

@adidahiya adidahiya Dec 13, 2017

Choose a reason for hiding this comment

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

we'll need to remember to remove this line when @cmslewis's Popover2 -> Popover change goes in.

"src/components/tabs/*",
// TODO (clewis): write tests for these component as part of the 2.0 effort:
"src/components/popover2/*",
"src/components/tag-input/*",
Expand All @@ -23,7 +28,7 @@ module.exports = function (config) {
entry: {
core: [
path.resolve(__dirname, "test/index.ts"),
path.resolve(__dirname, "src/blueprint.scss"),
path.resolve(__dirname, "dist/blueprint.css"),
],
},
}),
Expand Down
21 changes: 12 additions & 9 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"test": "npm-run-all -s compile:pre compile:cjs test:pre -p test:karma test:iso",
"test:pre": "tsc -p ./test",
"test:karma": "karma start",
"test:karma:debug": "karma start --browsers=Chrome --single-run=false --reporters=mocha --debug",
"test:iso": "mocha test/isotest.js",
"verify": "npm-run-all compile -p dist test lint"
},
Expand All @@ -36,27 +37,29 @@
"dom4": "^1.8",
"normalize.css": "^7.0.0",
"popper.js": "^1.12.6",
"pure-render-decorator": "^1.1",
"react-popper": "~0.7.4",
"tether": "^1.4",
"tslib": "^1.5.0"
},
"peerDependencies": {
"react": "^16.0.0 || ^15.0.1 || ^0.14",
"react-addons-css-transition-group": "^15.0.1 || ^0.14",
"react-dom": "^16.0.0 || ^15.0.1 || ^0.14"
"react": "^16.0.0",
"react-transition-group" :"^2.2.1",
"react-dom": "^16.0.0"
},
"devDependencies": {
"@blueprintjs/karma-build-scripts": "^0.2.0",
"@blueprintjs/node-build-scripts": "^0.2.0",
"enzyme": "~2.9.1",
"@blueprintjs/test-commons": "^0.1.0",
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"es6-shim": "^0.35.3",
"karma": "^1.7.1",
"mocha": "^4.0.1",
"npm-run-all": "^4.1.1",
"react": "^15.6.1",
"react-addons-css-transition-group": "^15.6.1",
"react-dom": "^15.6.1",
"react-test-renderer": "^15.6.1",
"react": "^16.2.0",
"react-transition-group": "^2.2.1",
"react-dom": "^16.2.0",
"react-test-renderer": "^16.2.0",
"tslint": "^5.8.0",
"typescript": "~2.6.2",
"webpack": "^3.9.1"
Expand Down
16 changes: 8 additions & 8 deletions packages/core/src/common/_react-transition.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
// Licensed under the terms of the LICENSE file distributed with this project.

/*
A mixin to generate the classes for a React CSSTransitionGroup which animates any number of CSS
A mixin to generate the classes for a React CSSTransition which animates any number of CSS
properties at once.

Transitioned properties are specificed as a map of property names to lists of (inital value, final
value). For enter & appear transitions, each property will transition from its initial to its final
value. For leave transitions, each property will transition in reverse, from final to initial.
value. For exit transitions, each property will transition in reverse, from final to initial.

**Simple example:**
`@include react-transition("pt-popover", (opacity: 0 1), $before: "&");`
Expand Down Expand Up @@ -39,17 +39,17 @@ $after: selector text to insert after transiton name (to select children)
$before, $after
);
@include react-transition-phase(
$name, "leave", $properties,
$name, "exit", $properties,
$duration, $easing, $delay,
$before, $after
);
}

/*
A mixin to generate the classes for one phase of a React CSSTransitionGroup.
`$phase` must be `appear` or `enter` or `leave`.
A mixin to generate the classes for one phase of a React CSSTransition.
`$phase` must be `appear` or `enter` or `exit`.
If `enter` phase is given then `appear` phase will be generated at the same time.
If `leave` phase is given then property values are animated in reverse, from final to initial.
If `exit` phase is given then property values are animated in reverse, from final to initial.

**Example:**
@include react-transition-phase(pt-toast, enter, $enter-translate, $before: "&");
Expand All @@ -68,11 +68,11 @@ If `leave` phase is given then property values are animated in reverse, from fin
$start-index: 1;
$end-index: 2;

@if ($phase == "leave") {
@if ($phase == "exit") {
$start-index: 2;
$end-index: 1;
} @else if ($phase != "enter" and $phase != "appear") {
@error "Unknown transition phase: #{$phase}. Expected appear|enter|leave.";
@error "Unknown transition phase: #{$phase}. Expected appear|enter|exit.";
}

#{transition-name($phase, $name, $before, $after)} {
Expand Down
73 changes: 73 additions & 0 deletions packages/core/src/common/abstractPureComponent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* Copyright 2015 Palantir Technologies, Inc. All rights reserved.
*
* Licensed under the terms of the LICENSE file distributed with this project.
*/

import * as React from "react";
import { isNodeEnv } from "./utils";

/**
* An abstract component that Blueprint components can extend
* in order to add some common functionality like runtime props validation.
*/
export abstract class AbstractPureComponent<P, S> extends React.PureComponent<P, S> {
/** Component displayName should be `public static`. This property exists to prevent incorrect usage. */
protected displayName: never;

// Not bothering to remove entries when their timeouts finish because clearing invalid ID is a no-op
private timeoutIds: number[] = [];

constructor(props?: P, context?: any) {
super(props, context);
if (!isNodeEnv("production")) {
this.validateProps(this.props);
}
}

public componentWillReceiveProps(nextProps: P & { children?: React.ReactNode }) {
if (!isNodeEnv("production")) {
this.validateProps(nextProps);
}
}

public componentWillUnmount() {
this.clearTimeouts();
}

/**
* Set a timeout and remember its ID.
* All stored timeouts will be cleared when component unmounts.
* @returns a "cancel" function that will clear timeout when invoked.
*/
public setTimeout(callback: () => void, timeout?: number) {
const handle = window.setTimeout(callback, timeout);
this.timeoutIds.push(handle);
return () => window.clearTimeout(handle);
}

/**
* Clear all known timeouts.
*/
public clearTimeouts = () => {
if (this.timeoutIds.length > 0) {
for (const timeoutId of this.timeoutIds) {
window.clearTimeout(timeoutId);
}
this.timeoutIds = [];
}
};

/**
* Ensures that the props specified for a component are valid.
* Implementations should check that props are valid and usually throw an Error if they are not.
* Implementations should not duplicate checks that the type system already guarantees.
*
* This method should be used instead of React's
* [propTypes](https://facebook.github.io/react/docs/reusable-components.html#prop-validation) feature.
* In contrast to propTypes, these runtime checks are _always_ run, not just in development mode.
*/
protected validateProps(_: P & { children?: React.ReactNode }) {
// implement in subclass
}
}
1 change: 1 addition & 0 deletions packages/core/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

export * from "./abstractComponent";
export * from "./abstractPureComponent";
export * from "./colors";
export * from "./intent";
export * from "./position";
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/alert/alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import * as classNames from "classnames";
import * as React from "react";

import { AbstractComponent, Classes, Intent, IProps } from "../../common";
import { AbstractPureComponent, Classes, Intent, IProps } from "../../common";
import { ALERT_WARN_CANCEL_PROPS } from "../../common/errors";
import { Button } from "../button/buttons";
import { Dialog } from "../dialog/dialog";
Expand Down Expand Up @@ -55,7 +55,7 @@ export interface IAlertProps extends IProps {
onConfirm(e: React.MouseEvent<HTMLButtonElement>): void;
}

export class Alert extends AbstractComponent<IAlertProps, {}> {
export class Alert extends AbstractPureComponent<IAlertProps, {}> {
public static defaultProps: IAlertProps = {
confirmButtonText: "OK",
isOpen: false,
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/components/button/buttonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import * as classNames from "classnames";
import * as PureRender from "pure-render-decorator";
import * as React from "react";
import * as Classes from "../../common/classes";
import { IProps } from "../../common/props";
Expand Down Expand Up @@ -38,8 +37,7 @@ export interface IButtonGroupProps extends IProps, React.HTMLProps<HTMLDivElemen

// this component is simple enough that tests would be purely tautological.
/* istanbul ignore next */
@PureRender
export class ButtonGroup extends React.Component<IButtonGroupProps, {}> {
export class ButtonGroup extends React.PureComponent<IButtonGroupProps, {}> {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should be able to drop these empty {} state types, as the React types now provide a default: interface Component<P = {}, S = {}>.

though it's fine to not do this now, or ever.

public static displayName = "Blueprint.ButtonGroup";

public render() {
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/components/callout/callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import * as classNames from "classnames";
import * as PureRender from "pure-render-decorator";
import * as React from "react";

import { Classes, IIntentProps, IProps } from "../../common";
Expand All @@ -25,8 +24,7 @@ export interface ICalloutProps extends IIntentProps, IProps {
title?: string;
}

@PureRender
export class Callout extends React.Component<ICalloutProps & React.HTMLAttributes<HTMLDivElement>, {}> {
export class Callout extends React.PureComponent<ICalloutProps & React.HTMLAttributes<HTMLDivElement>, {}> {
public render() {
const { className, children, iconName, intent, title, ...htmlProps } = this.props;
const classes = classNames(
Expand Down
4 changes: 1 addition & 3 deletions packages/core/src/components/card/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import * as classNames from "classnames";
import * as PureRender from "pure-render-decorator";
import * as React from "react";
import * as Classes from "../../common/classes";
import { IProps } from "../../common/props";
Expand Down Expand Up @@ -54,8 +53,7 @@ const ELEVATION_CLASSES = [
Classes.ELEVATION_4,
];

@PureRender
export class Card extends React.Component<ICardProps, {}> {
export class Card extends React.PureComponent<ICardProps, {}> {
public static displayName = "Blueprint.Card";
public static defaultProps: ICardProps = {
elevation: Elevation.ZERO,
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/collapse/collapse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import * as classNames from "classnames";
import * as React from "react";

import { AbstractComponent } from "../../common/abstractComponent";
import { AbstractPureComponent } from "../../common/abstractPureComponent";
import * as Classes from "../../common/classes";
import { IProps } from "../../common/props";

Expand Down Expand Up @@ -83,7 +83,7 @@ export enum AnimationStates {
* isOpen = false: OPEN -> CLOSING_START -> CLOSING_END -> CLOSED
* These are all animated.
*/
export class Collapse extends AbstractComponent<ICollapseProps, ICollapseState> {
export class Collapse extends AbstractPureComponent<ICollapseProps, ICollapseState> {
public static displayName = "Blueprint.Collapse";

public static defaultProps: ICollapseProps = {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/context-menu/contextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as classNames from "classnames";
import * as React from "react";
import * as ReactDOM from "react-dom";

import { AbstractComponent } from "../../common/abstractComponent";
import { AbstractPureComponent } from "../../common/abstractPureComponent";
import * as Classes from "../../common/classes";
import { Position } from "../../common/position";
import { safeInvoke } from "../../common/utils";
Expand All @@ -33,7 +33,7 @@ const TETHER_OPTIONS = {
const TRANSITION_DURATION = 100;

/* istanbul ignore next */
class ContextMenu extends AbstractComponent<{}, IContextMenuState> {
class ContextMenu extends AbstractPureComponent<{}, IContextMenuState> {
public state: IContextMenuState = {
isOpen: false,
};
Expand Down
6 changes: 3 additions & 3 deletions packages/core/src/components/dialog/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import * as classNames from "classnames";
import * as React from "react";

import { AbstractComponent } from "../../common/abstractComponent";
import { AbstractPureComponent } from "../../common/abstractPureComponent";
import * as Classes from "../../common/classes";
import * as Errors from "../../common/errors";
import { IProps } from "../../common/props";
Expand Down Expand Up @@ -56,13 +56,13 @@ export interface IDialogProps extends IOverlayableProps, IBackdropProps, IProps
title?: string | JSX.Element;

/**
* Name of the transition for internal `CSSTransitionGroup`.
* Name of the transition for internal `CSSTransition`.
* Providing your own name here will require defining new CSS transition properties.
*/
transitionName?: string;
}

export class Dialog extends AbstractComponent<IDialogProps, {}> {
export class Dialog extends AbstractPureComponent<IDialogProps, {}> {
public static defaultProps: IDialogProps = {
canOutsideClickClose: true,
isOpen: false,
Expand Down
6 changes: 2 additions & 4 deletions packages/core/src/components/editable-text/editableText.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
*/

import * as classNames from "classnames";
import * as PureRender from "pure-render-decorator";
import * as React from "react";

import { AbstractComponent } from "../../common/abstractComponent";
import { AbstractPureComponent } from "../../common/abstractPureComponent";
import * as Classes from "../../common/classes";
import * as Keys from "../../common/keys";
import { IIntentProps, IProps } from "../../common/props";
Expand Down Expand Up @@ -105,8 +104,7 @@ export interface IEditableTextState {
const BUFFER_WIDTH_EDGE = 5;
const BUFFER_WIDTH_IE = 30;

@PureRender
export class EditableText extends AbstractComponent<IEditableTextProps, IEditableTextState> {
export class EditableText extends AbstractPureComponent<IEditableTextProps, IEditableTextState> {
public static defaultProps: IEditableTextProps = {
confirmOnEnterKey: false,
defaultValue: "",
Expand Down
Loading