-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Conversation
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. |
@@ -61,6 +62,12 @@ export interface IHotkeyProps { | |||
*/ | |||
stopPropagation?: boolean; | |||
|
|||
/** | |||
* Space-delimited string of class names applied to the | |||
* keyCombo contained in the hotkey. |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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"], |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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}>`); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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`, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extra space after >
There was a problem hiding this comment.
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)) { |
There was a problem hiding this comment.
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")
?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Cleaned up isotestsPreview: documentation | table |
packages/table/test/isotest.js
Outdated
"CopyCellsMenuItem" | ||
] | ||
|
||
const skipList = [ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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!
Made className prop for resizeHandlePreview: documentation | table |
There was a problem hiding this 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, |
There was a problem hiding this comment.
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.
There was a problem hiding this 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[] = [], |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
packages/core/test/isotest.js
Outdated
"Alert", | ||
"Dialog", | ||
"MenuItem", | ||
"Popover2", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Documenting new paramPreview: documentation | table |
Not sure why |
@kmblake it's just a flaky test. Try re-rerunning from the Circle UI. |
There was a problem hiding this 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); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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.
Replaced shallow with render in className testPreview: documentation | table |
children[componentName], | ||
); | ||
if (classNameChildList.includes(componentName)) { | ||
assert.isAtLeast(Enzyme.render(element).find(".test").length, 1); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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`, () => { |
There was a problem hiding this comment.
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
@kmblake I just pushed a commit, attempting to fix the build. i've refactored the className test to use assuming the build will fail again on a few components--i've got local fixes but want to know which ones are actually necessary. |
fix className in QueryList renderer (per #1993)
refactor className isotest:Preview: documentation | landing | table |
oops i fucked up, these are all false positives. and now i can't make it actually fail correctly. |
ok I just removed the new isotest entirely -- writing this test in a generic way is just too finicky. |
remove className isotest entirely -- false positives, just no good.Preview: documentation | landing | table |
* Space-delimited string of class names applied to the | ||
* `KeyCombo` contained in the hotkey. | ||
*/ | ||
keyComboClassName?: string; |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
remove stray comment and keyComboClassNamePreview: documentation | landing | table |
Checklist
Changes proposed in this pull request:
fix className support for the following components: