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

className prop consistency #1950

Merged
merged 14 commits into from
Jan 25, 2018
Merged

className prop consistency #1950

merged 14 commits into from
Jan 25, 2018

Conversation

kmblake
Copy link
Contributor

@kmblake kmblake commented Dec 20, 2017

Checklist

Changes proposed in this pull request:

fix className support for the following components:

  • Hotkey
  • Hotkeys
  • KeyCombo
  • QueryList (select)
  • ResizeHandle (table)

@palantirtech
Copy link
Member

Thanks for your interest in palantir/blueprint, @kmblake! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

@giladgray giladgray changed the title Kb/class name consistency className prop consistency Dec 20, 2017
@@ -61,6 +62,12 @@ export interface IHotkeyProps {
*/
stopPropagation?: boolean;

/**
* Space-delimited string of class names applied to the
* keyCombo contained in the hotkey.
Copy link
Contributor

Choose a reason for hiding this comment

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

backticks around "KeyCombo" (also capital K)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -52,6 +53,7 @@ export class Hotkeys extends AbstractPureComponent<IHotkeysProps, {}> {

let lastGroup = null as string;
const elems = [] as JSX.Element[];
const rootClasses = classNames("pt-hotkey-column", this.props.className);
Copy link
Contributor

Choose a reason for hiding this comment

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

move this assignment after the for loop, right before the return -- this location separates the loop vars from their usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved it!

*/
export function generateIsomorphicTests(
Components: { [name: string]: any },
props: { [name: string]: any },
children: { [name: string]: React.ReactNode },
skipList: string[] = [],
renderSkipList: string[] = [],
classNameSkipList: string[] = ["Alert", "Dialog", "MenuItem", "Popover2", "Portal", "Toaster", "Tooltip2"],
Copy link
Contributor

Choose a reason for hiding this comment

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

remove this default value, use []. set this array in packages/core/test/isotest.js

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah that makes sense! Moved all customizations to packages/core/test/isotest.js

@@ -55,6 +57,24 @@ export function generateIsomorphicTests(
Enzyme.render(element);
});
}
if (classNameSkipList.includes(componentName)) {
it.skip(`<${componentName}>`);
Copy link
Contributor

Choose a reason for hiding this comment

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

use the same test name as line 63.

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 refactored this so that if a component is on the skipList, both the render and className tests will be skipped. If rendering fails, no use searching for a class

if (classNameSkipList.includes(componentName)) {
it.skip(`<${componentName}>`);
} else {
it(`<${componentName}> className is applied to outer element`, () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

extra space after >

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

@@ -55,6 +57,24 @@ export function generateIsomorphicTests(
Enzyme.render(element);
});
}
if (classNameSkipList.includes(componentName)) {
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 not so much about skipping as about elements where className is not on the root -- but they should still support className.

maybe we can always have a unit test but if the component is in the list then we use Enzyme.render(element).find(".test")?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Retitled to classNameChildList and made it so for anything on that list the test will search the whole component tree for the class.

className: "test",
iconName: "pt-icon-build",
inline: true,
lazy: false,
Copy link
Contributor

Choose a reason for hiding this comment

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

why are these three props necessary? should only have to set className, other required props should come from props arg itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved these to the isotest.js files so they will only be used for the components that need them

@blueprint-bot
Copy link

Cleaned up isotests

Preview: documentation | table

"CopyCellsMenuItem"
]

const skipList = [
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@giladgray Classname doesn't propagate for these three components, but i'm not sure of the best way to handle these. It looks like they are just wrappers for eventHandlers, in which case maybe className doesn't need to propagate?

Copy link
Contributor

Choose a reason for hiding this comment

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

ResizeHandle - add support

the other two, you're right, they're the exceptions!

@blueprint-bot
Copy link

Made className prop for resizeHandle

Preview: documentation | table

Copy link
Contributor

@giladgray giladgray left a comment

Choose a reason for hiding this comment

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

looks great @kmblake!!

{
...props[componentName],
className: "test",
} as any,
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 as any necessary? I imagine it shouldn't be.

cmslewis
cmslewis previously approved these changes Dec 21, 2017
Copy link
Contributor

@cmslewis cmslewis left a comment

Choose a reason for hiding this comment

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

One nit but nothing blocking.

@@ -38,6 +39,7 @@ export function generateIsomorphicTests(
props: { [name: string]: any },
children: { [name: string]: React.ReactNode },
skipList: string[] = [],
classNameChildList: string[] = [],
Copy link
Contributor

Choose a reason for hiding this comment

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

Need to document this new param in the function comment above.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done!

"Alert",
"Dialog",
"MenuItem",
"Popover2",
Copy link
Contributor

Choose a reason for hiding this comment

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

Will need to return and remove the 2s here after #1946 and #1370 merge.

@blueprint-bot
Copy link

Documenting new param

Preview: documentation | table

@kmblake
Copy link
Contributor Author

kmblake commented Jan 8, 2018

Not sure why brings focus to overlay if autoFocus=true suddenly started failing...it's passing when I run the test locally

@cmslewis
Copy link
Contributor

cmslewis commented Jan 8, 2018

@kmblake it's just a flaky test. Try re-rerunning from the Circle UI.

Copy link
Contributor

@giladgray giladgray left a comment

Choose a reason for hiding this comment

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

@kmblake this is almost there! just two little things and i think we're good to go. let me know if you're too busy, I'm happy to jump in.

children[componentName],
);
if (classNameChildList.includes(componentName)) {
assert.isAtLeast(Enzyme.shallow(element).find(".test").length, 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

shallow and render are very different... we want to use render only here as it produces a DOM tree, whereas shallow produces some Enzyme-only tree that doesn't actually assert server-side-rendering success. should be possible to simply replace the word shallow with render, it still has a find method.

@@ -32,12 +33,15 @@ function isReactClass(Component: any): boolean {
* @param props custom props per component
* @param children custom children per component
* @param skipList array of component names to skip
* @param classNameChildList array of component names for which className is legitimately passed down to
* child element
Copy link
Contributor

Choose a reason for hiding this comment

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

array of component names where className is rendered on an arbitrary child element, rather than directly on the root element.

@blueprint-bot
Copy link

Replaced shallow with render in className test

Preview: documentation | table

children[componentName],
);
if (classNameChildList.includes(componentName)) {
assert.isAtLeast(Enzyme.render(element).find(".test").length, 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

looks like this change caused some tests to fail, but this is definitely more correct.

could add { inline: true } prop to those components to keep everything inside the container element.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems like this gets a little tricky for a few components. Alert and Dialog render className on a child div within an Overlay element, but that div isn't rendered unless isOpen: true is passed as a prop. But if isOpen: true is passed in, then we get an error about "document not defined." Is there an easy way to mock the document for these components to attach to?

Copy link
Contributor

Choose a reason for hiding this comment

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

aw nuts. there is certainly not an easy way to mock the document. i can take a look at this.

@@ -54,6 +58,21 @@ export function generateIsomorphicTests(
// errors will fail the test and log full stack traces to the console. nifty!
Enzyme.render(element);
});
it(`<${componentName}> className is applied to outer element`, () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

this test name is not always accurate... might want to do the classNameChildList check outside this it() so we can change the test name?

- use Enzyme.shallow + disable lifecycle methods to get JSX tree
- don't care where className appears in tree, just that it does
@giladgray
Copy link
Contributor

@kmblake I just pushed a commit, attempting to fix the build. i've refactored the className test to use Enzyme.shallow and disabling lifecycle methods to find className anywhere in the JSX tree without overcomplicating the render. nicely, this allowed me to remove the 5th argument you added to the isotest function as all components look the same in this manner: Portal is just a node like any other.

assuming the build will fail again on a few components--i've got local fixes but want to know which ones are actually necessary.

Gilad Gray added 2 commits January 11, 2018 13:52
fix className in QueryList renderer (per #1993)
@blueprint-bot
Copy link

refactor className isotest:

Preview: documentation | landing | table

@giladgray
Copy link
Contributor

giladgray commented Jan 11, 2018

oops i fucked up, these are all false positives. and now i can't make it actually fail correctly.

@giladgray
Copy link
Contributor

giladgray commented Jan 11, 2018

ok I just removed the new isotest entirely -- writing this test in a generic way is just too finicky.

@blueprint-bot
Copy link

remove className isotest entirely -- false positives, just no good.

Preview: documentation | landing | table

@adidahiya adidahiya added this to the 2.0.0-beta.1 milestone Jan 12, 2018
@adidahiya adidahiya dismissed stale reviews from giladgray and cmslewis January 12, 2018 20:45

addressed

* Space-delimited string of class names applied to the
* `KeyCombo` contained in the hotkey.
*/
keyComboClassName?: 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 do we need this?

Copy link
Contributor

Choose a reason for hiding this comment

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

we don't strictly need it and it's probably safe to remove. shall i do that?

@@ -3,6 +3,7 @@
* Licensed under the terms of the LICENSE file distributed with this project.
*/

// @ts-check
Copy link
Contributor

Choose a reason for hiding this comment

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

🙏

@@ -32,6 +32,7 @@ function isReactClass(Component: any): boolean {
* @param props custom props per component
* @param children custom children per component
* @param skipList array of component names to skip
* element, rather than directly on the root element
Copy link
Contributor

Choose a reason for hiding this comment

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

stray comment? what's this?

@adidahiya adidahiya modified the milestones: 2.0.0-beta.1, 2.0.0 Jan 12, 2018
@adidahiya adidahiya changed the base branch from master to develop January 15, 2018 17:12
@blueprint-bot
Copy link

remove stray comment and keyComboClassName

Preview: documentation | landing | table

@giladgray giladgray merged commit f4204cc into develop Jan 25, 2018
@giladgray giladgray deleted the kb/className-consistency branch January 25, 2018 19:13
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.

6 participants