Skip to content

Commit

Permalink
add isotest for className prop (#3119)
Browse files Browse the repository at this point in the history
* four args become two. add className isotest.

refactor generateIsomorphicTests() to use config object in mapped type

* refactor isotest suites to new config object
  • Loading branch information
giladgray authored Nov 1, 2018
1 parent e4905b3 commit 567dd08
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 107 deletions.
79 changes: 57 additions & 22 deletions packages/core/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,64 @@ const { generateIsomorphicTests } = require("@blueprintjs/test-commons");
const React = require("react");
const Core = require("../lib/cjs");

const tooltipContent = { content: React.createElement("h1", {}, "content") };
const customProps = {
Hotkey: { combo: "mod+s", global: true, label: "save" },
Icon: { iconName: "build" },
KeyCombo: { combo: "?" },
OverflowList: { items: [], overflowRenderer: () => null, visibleItemRenderer: () => null },
Overlay: { lazy: false, usePortal: false },
PanelStack: { initialPanel: { component: () => null, props: {}, title: "" } },
TagInput: { values: ["foo", "bar", "baz"] },
Tooltip: tooltipContent,
Toaster: { usePortal: false },
};

const requiredChild = React.createElement("button");
const customChildren = {
Hotkeys: React.createElement(Core.Hotkey, customProps.Hotkey),
Popover: requiredChild,
ResizeSensor: requiredChild,
Tabs: React.createElement(Core.Tab, { key: 1, id: 1, title: "Tab one" }),
Tooltip: requiredChild,
Toaster: React.createElement(Core.Toast, { message: "Toast" }),
};
const hotkeyProps = { combo: "mod+s", global: true, label: "save" };

describe("Core isomorphic rendering", () => {
generateIsomorphicTests(Core, customProps, customChildren);
generateIsomorphicTests(Core, {
Alert: {
props: { isOpen: true, usePortal: false },
},
Dialog: {
props: { isOpen: true, usePortal: false },
},
Hotkey: {
props: hotkeyProps,
},
Hotkeys: {
children: React.createElement(Core.Hotkey, hotkeyProps),
},
Icon: {
props: { icon: "build" },
},
KeyCombo: {
props: { combo: "?" },
},
OverflowList: {
props: { items: [], overflowRenderer: () => null, visibleItemRenderer: () => null },
},
Overlay: {
props: { lazy: false, usePortal: false },
},
PanelStack: {
props: {
initialPanel: { component: () => null, props: {}, title: "" }
},
children: ""
},
Portal: {
className: false, // only renders in browser (`document`)
},
Popover: {
children: requiredChild,
},
ResizeSensor: {
children: requiredChild,
className: false,
},
Tabs: {
children: React.createElement(Core.Tab, { key: 1, id: 1, title: "Tab one" }),
},
TagInput: {
props: { values: ["foo", "bar", "baz"] },
},
Tooltip: {
props: { content: React.createElement("h1", {}, "content") },
children: requiredChild
},
Toaster: {
props: { usePortal: false },
children: React.createElement(Core.Toast, { message: "Toast" })
},
});
});
7 changes: 3 additions & 4 deletions packages/datetime/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ describe("DateTime isomorphic rendering", () => {
generateIsomorphicTests(
DateTime,
{
"DateInput": formatProps,
"DateRangeInput": formatProps,
},
{}
DateInput: { props: formatProps },
DateRangeInput: { props: formatProps },
}
);
});
6 changes: 1 addition & 5 deletions packages/icons/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,5 @@ const React = require("react");
const Icons = require("../lib/cjs");

describe("Icons isomorphic rendering", () => {
generateIsomorphicTests(
Icons,
{},
{}
);
generateIsomorphicTests(Icons);
});
52 changes: 22 additions & 30 deletions packages/select/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,27 @@ const { generateIsomorphicTests } = require("@blueprintjs/test-commons");
const React = require("react");
const Select = require("../lib/cjs");

const customChildren = {
};

const customProps = {
MultiSelect: {
items: [],
query: "",
selectedItems: [],
tagRenderer: () => null,
},
QueryList: {
// needs at least one handler or it returns undefined
renderer: () => null
},
Select: {
items: [],
},
Suggest: {
items: [],
},
Omnibar: {
items: [],
}
};

const skipList = [
"QueryList", // doesn't render any DOM itself
]

describe("Select isomorphic rendering", () => {
generateIsomorphicTests(Select, customProps, customChildren, skipList);
generateIsomorphicTests(Select, {
MultiSelect: {
props: { items: [], query: "", selectedItems: [], tagRenderer: () => null },
},
QueryList: {
// needs at least one handler or it returns undefined
props: { renderer: () => null },
skip: true,
},
Select: {
props: { items: [] },
},
Suggest: {
props: { items: [] },
},
Omnibar: {
props: { items: [], isOpen: true, overlayProps: { usePortal: false } },
},
QueryList: {
skip: true,
}
});
});
24 changes: 7 additions & 17 deletions packages/table/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,15 @@ const { generateIsomorphicTests } = require("@blueprintjs/test-commons");
const React = require("react");
const Table = require("../lib/cjs");

const customProps = {
ResizeHandle: {
// needs at least one handler or it returns undefined
onDoubleClick: () => undefined,
},
};

const skipList = [
// Pass-through renders
"DragSelectable",
"Draggable",
]


describe("Table isomorphic rendering", () => {
generateIsomorphicTests(
Table,
customProps,
{},
skipList
{
// Pass-through renders
DragSelectable: { skip: true },
Draggable: { skip: true },
// needs at least one handler or it returns undefined
ResizeHandle: { props: { onDoubleClick: () => undefined } },
}
);
});
64 changes: 43 additions & 21 deletions packages/test-commons/src/generateIsomorphicTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import "../../bootstrap";

import { equal } from "assert";
import * as Enzyme from "enzyme";
import * as React from "react";

Expand All @@ -18,34 +19,55 @@ function isReactClass(Component: any): Component is React.ComponentClass<any> {
);
}

export interface IIsomorphicTestConfig {
/** Required `children` for successful render. */
children?: React.ReactNode;
/** Whether to test `className`. */
className?: boolean;
/** Required `props` for successful render. */
props?: object;
/** Whether to skip this component entirely. */
skip?: boolean;
}

/**
* Tests that each ComponentClass in Components can be isomorphically rendered on the server.
* @param Components namespace export from package
* @param props custom props per component
* @param children custom children per component
* @param skipList array of component names to skip
*/
export function generateIsomorphicTests(
Components: { [name: string]: any },
props: { [name: string]: any },
children: { [name: string]: React.ReactNode },
skipList: string[] = [],
export function generateIsomorphicTests<T extends { [name: string]: any }>(
/** Namespace import of all components to test. */
Components: T,
/** Configuration per component. This is a mapped type supporting all keys in `Components`. */
config: { [P in keyof T]?: IIsomorphicTestConfig } = {},
) {
function render(name: string, extraProps?: object) {
const { children, props }: IIsomorphicTestConfig = config[name] || {};
const finalProps = extraProps ? { ...props, ...extraProps } : props;
// Render to static HTML, just as a server would.
// We care merely that `render()` succeeds: it can be server-rendered.
// Errors will fail the test and log full stack traces to the console. Nifty!
const element = React.createElement(Components[name], finalProps, children);
return Enzyme.render(element);
}

Object.keys(Components)
.sort()
.filter(name => isReactClass(Components[name]))
.forEach(componentName => {
const Component = Components[componentName];
if (isReactClass(Component)) {
if (skipList.includes(componentName)) {
it.skip(`<${componentName}>`);
} else {
it(`<${componentName}>`, () => {
// render to static HTML, just as a server would.
// we care merely that `render()` succeeds: it can be server-rendered.
// errors will fail the test and log full stack traces to the console. nifty!
Enzyme.render(React.createElement(Component, props[componentName], children[componentName]));
});
}
const { className, skip }: IIsomorphicTestConfig = config[componentName] || {};
if (skip) {
it.skip(`<${componentName}>`);
return;
}

it(`<${componentName}>`, () => render(componentName));
if (className === false) {
it.skip(`<${componentName} className>`);
} else {
it(`<${componentName} className>`, () => {
const testClass = "test-test-test";
const doc = render(componentName, { className: testClass });
equal(doc.find(`.${testClass}`).length + doc.filter(`.${testClass}`).length, 1);
});
}
});
}
9 changes: 1 addition & 8 deletions packages/timezone/test/isotest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ const { generateIsomorphicTests } = require("@blueprintjs/test-commons");
const React = require("react");
const Timezone = require("../lib/cjs");

const skipList = []

describe("Timezone isomorphic rendering", () => {
generateIsomorphicTests(
Timezone,
{},
{},
skipList
);
generateIsomorphicTests(Timezone);
});

1 comment on commit 567dd08

@blueprint-bot
Copy link

Choose a reason for hiding this comment

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

add isotest for className prop (#3119)

Previews: documentation | landing | table

Please sign in to comment.