Compare commits

...
Author SHA1 Message Date
bendtherules b16012f81e Release v0.0.5 2019-08-29 17:10:43 +05:30
bendtherules 113674df2f Update package-lock 2019-08-29 17:09:25 +05:30
bendtherules 88eb62298e Release v0.0.4 2019-08-29 17:01:43 +05:30
bendtherules 8e484fc074 TODO - findAllNodes added 2019-08-28 09:01:16 +05:30
bendtherules a88e0e0f07 Readme - Update with correct import statements 2019-08-28 09:00:57 +05:30
bendtherules a1204cfc1b lib - export utils from main export 2019-08-27 22:58:47 +05:30
bendtherules ceaa1eee32 TODO - Separate out major compatibility changes into diff item 2019-08-25 17:26:28 +05:30
bendtherules 3c5ea67992 Add testcase - traverseGenerator-skipped
Some simple cases covered. Needs more thought out cases with combination
2019-08-11 22:12:23 +05:30
bendtherules 395dc281ce test.traverseGenerator-ordered - Fix test group title 2019-08-11 20:19:13 +05:30
bendtherules 3e062ef911 Add testcase - getRootFiberNodeFromDOM - without any element as input 2019-08-10 17:20:20 +05:30
bendtherules e3750e9b50 Add TODO for getRootFiberNodeFromDOM changes needed (skip-ci) 2019-08-10 17:13:40 +05:30
bendtherules e1dec601e7 Add testcases - utils.getRootFiberNodeFromDOM 2019-08-10 17:08:32 +05:30
bendtherules d6d32fd847 Add testcase - utils.doesElementContainRootFiberNode 2019-08-10 16:17:01 +05:30
bendtherules 7aff88ecb8 package.json - Remove post-commit hook 2019-08-10 13:49:28 +05:30
bendtherules 400757182f Modify lint-staged - Run prettier and eslint only on changed files 2019-08-10 13:46:21 +05:30
bendtherules 6cd41bc4bd Modify 'lint' cmd - Run eslint for jsx.tsx also 2019-08-10 13:04:17 +05:30
bendtherules 5a33b3272e utils - export doesElementContainRootFiberNode 2019-08-10 13:01:07 +05:30
bendtherules e7e1415039 Add testcases - utils.isConstructorComponentClass 2019-08-10 12:59:40 +05:30
bendtherules 7e676b0edc Add testcases - utils.isConstructorFunctionComponent 2019-08-10 12:58:46 +05:30
bendtherules 9ebc534cc3 Modify isConstructorFunctionComponent - Check type is function 2019-08-10 12:54:30 +05:30
bendtherules d7276eff9e Modify utils.isConstructor* - Allow null type as input 2019-08-10 11:26:39 +05:30
bendtherules c5adcb3152 Add testcase - utils.isConstructorHtmlLike 2019-08-10 10:49:33 +05:30
bendtherules e64d51a3e6 Modify util.isConstructorHtmlLike - Allow null typeas input 2019-08-10 10:46:42 +05:30
bendtherules 887f4b95d1 Modify utils - doesElementContainRootFiberNode also checks for _internalRoot now 2019-08-10 10:37:12 +05:30
bendtherules 39080755ef Add testcase - isNodeComponentClass 2019-08-10 09:58:15 +05:30
bendtherules 69c1d2db86 Edit test title in utils.isNodeFunctionComponent 2019-08-10 01:49:40 +05:30
bendtherules 86216d3b05 Add testcase - utils.isNodeHtmlLike - Add negative test cases where it is false 2019-08-10 01:44:39 +05:30
bendtherules 933639e0ba Add testcase - utils.isNodeFunctionComponent 2019-08-10 01:43:14 +05:30
bendtherules 91ab867f19 Update package-lock 2019-08-09 23:02:15 +05:30
bendtherules 8f29fd8eea Fix prettier - mountInEnzyme
Was missed due to non-installation of husky in this machine
2019-08-09 23:00:08 +05:30
bendtherules c3ca45928a Add testcase - utils.isNodeHtmlLike
Tests isNodeHtmlLike and isNodeNotHtmlLike
2019-08-09 22:28:02 +05:30
bendtherules 2aa7a9bbf3 Test utils - mountInEnzyme - support loading intrinsic elements 2019-08-09 22:10:08 +05:30
bendtherules fb23260efe Add testcase - findNodeByComponentRef-negative
Check cases where ref is not found in fiber tree
2019-08-09 11:54:50 +05:30
bendtherules 6f5826d398 Add testcase - findNodeByComponent-negative
Test cases where component is not found
2019-08-09 10:05:24 +05:30
21 changed files with 1103 additions and 38 deletions
+15 -15
View File
@@ -1,18 +1,18 @@
{
"dist/react-fiber-traverse.cjs.development.js": {
"bundled": 7398,
"minified": 3036,
"gzipped": 967
"bundled": 9674,
"minified": 4533,
"gzipped": 1335
},
"dist/react-fiber-traverse.cjs.production.js": {
"bundled": 7398,
"minified": 3036,
"gzipped": 967
"bundled": 9674,
"minified": 4533,
"gzipped": 1335
},
"dist/react-fiber-traverse.esm.js": {
"bundled": 7048,
"minified": 2736,
"gzipped": 869,
"bundled": 9312,
"minified": 4229,
"gzipped": 1245,
"treeshaked": {
"rollup": {
"code": 49,
@@ -24,13 +24,13 @@
}
},
"dist/react-fiber-traverse.umd.development.js": {
"bundled": 32560,
"minified": 8698,
"gzipped": 3085
"bundled": 34862,
"minified": 9669,
"gzipped": 3394
},
"dist/react-fiber-traverse.umd.production.js": {
"bundled": 32560,
"minified": 8698,
"gzipped": 3085
"bundled": 34862,
"minified": 9669,
"gzipped": 3394
}
}
+2 -3
View File
@@ -12,13 +12,12 @@
```ts
import { render } from 'react-dom'
import { findNodeByComponentName } from 'react-fiber-traverse'
import { getRootFiberNodeFromDOM } from 'react-fiber-traverse/utils'
import { findNodeByComponentName, Utils } from 'react-fiber-traverse'
const rootElement = document.getElementById('root');
render(<App>, 'root');
const rootFiberNode = getRootFiberNodeFromDOM(rootElement);
const rootFiberNode = Utils.getRootFiberNodeFromDOM(rootElement);
const someFiberNode = findNodeByComponentName(rootFiberNode, 'SomeComponentName'); // <- returns FiberNode for first usage of 'SomeComponentName'
// Say, if SomeComponentName renders (<div>Some text</div>)
+12
View File
@@ -1,4 +1,16 @@
# TODOs
1. Write docs and examples
2. Reduce testcase boilerplate code for similar tests
3. Publish to npm
4. Build some demo
5. Add `findAllNodes` helpers which searches all usages of the components - by name or class
6. Fix getRootFiberNodeFromDOM and related helpers -
- .\_internalRoot is not present is 16.0.0 but present in 16.9.0
- actual node is available 2 levels nested inside this root node
- add testcase to run across all versions of React 16.0.0 (dev+prod) and above (because internals change)
7. Make it work with older React versions
8. Make it work with non React-DOM renderers
+10 -1
View File
@@ -1,3 +1,12 @@
module.exports = {
"*.{js,jsx,ts,tsx}": () => "run-s check:* lint"
"*.{js,jsx,ts,tsx}": filenames => {
// Escape filenames and join by space
const joinedFilenames = filenames.map(str => `"${str}"`).join(" ");
return [
"run-s check:!(format)",
`npm run check:format -- ${joinedFilenames}`,
`npm run _lint -- ${joinedFilenames}`
];
// `run-s check:!(format) "check:format -- ${joinedFilenames}" "_lint -- ${joinedFilenames}"`;
}
};
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "react-fiber-traverse",
"version": "0.0.3",
"version": "0.0.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "react-fiber-traverse",
"version": "0.0.3",
"version": "0.0.5",
"description": "Traverse and other utils on top of React fiber tree",
"main": "dist/index.js",
"module": "dist/react-fiber-traverse.esm.js",
@@ -24,7 +24,8 @@
"compile": "tsc -p tsconfig.base.json",
"docs": "npx typedoc ./src/",
"format": "prettier --write \"**/*.{js,ts,tsx}\"",
"lint": "eslint . --ext .js,.ts",
"_lint": "eslint --ext .js,.ts,.jsx,.tsx",
"lint": "npm run _lint -- .",
"postbundle": "del compiled && cp-cli ./index.js ./dist/index.js",
"postversion": "git push && git push --tags && npm publish",
"release": "npm version -m 'Release v%s'",
@@ -41,8 +42,7 @@
},
"husky": {
"hooks": {
"pre-commit": "lint-staged",
"post-commit": "npm run fix:format"
"pre-commit": "lint-staged"
}
},
"repository": {
+3 -1
View File
@@ -4,11 +4,13 @@ import {
findNodeByComponentRef,
findNodeByComponentName
} from "./findNode";
import * as Utils from "./utils";
export {
traverse,
traverseGenerator,
findNodeByComponent,
findNodeByComponentRef,
findNodeByComponentName
findNodeByComponentName,
Utils
};
+13 -6
View File
@@ -7,6 +7,7 @@ import {
FiberNodeDOMContainer
} from "./mocked-types";
// Support null in all of these
function isNodeHtmlLike(node: FiberNode): node is FiberNodeisHTMLLike {
return typeof node.type === "string" || node.type === null;
}
@@ -30,8 +31,8 @@ function isNodeComponentClass(
}
function isConstructorHtmlLike(
ctr: React.ElementType
): ctr is Exclude<React.ElementType, React.ComponentType> {
ctr: React.ElementType | null
): ctr is Exclude<React.ElementType | null, React.ComponentType> {
if (typeof ctr === "string" || ctr === null) {
return true;
}
@@ -39,7 +40,7 @@ function isConstructorHtmlLike(
}
function isConstructorComponentClass(
ctr: React.ElementType
ctr: React.ElementType | null
): ctr is React.ComponentClass {
if (isConstructorHtmlLike(ctr)) {
return false;
@@ -56,15 +57,20 @@ function isConstructorComponentClass(
}
function isConstructorFunctionComponent(
ctr: React.ElementType
ctr: React.ElementType | null
): ctr is React.FunctionComponent {
return !isConstructorComponentClass(ctr);
return typeof ctr === "function" && !isConstructorComponentClass(ctr);
}
function doesElementContainRootFiberNode(
element: Element
): element is FiberNodeDOMContainer {
return element.hasOwnProperty("_reactRootContainer");
return (
element.hasOwnProperty("_reactRootContainer") &&
(element as (Element & {
_reactRootContainer: any;
}))._reactRootContainer.hasOwnProperty("_internalRoot")
);
}
/**
@@ -101,5 +107,6 @@ export {
isConstructorHtmlLike,
isConstructorComponentClass,
isConstructorFunctionComponent,
doesElementContainRootFiberNode,
getRootFiberNodeFromDOM
};
+177
View File
@@ -0,0 +1,177 @@
import * as React from "react";
// Import stuff from src
import { findNodeByComponent } from "../src";
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import getWrappedComponent from "./utils/getWrappedComponent";
// Import test helpers and sample components
import CDepth1 from "./sample-components/depth-1-simple";
import FnDepth1 from "./sample-components/depth-1-fn-simple";
import { createClassComponent } from "./utils/createComponent";
describe("findNodeByComponent", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("missing", () => {
it("should not work for top-level class with same component name", () => {
const WrappedC = getWrappedComponent(CDepth1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeCDepth1 = createClassComponent(CDepth1.name);
const found = findNodeByComponent(rootNode, FakeCDepth1);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for top-level class with different component name", () => {
const WrappedC = getWrappedComponent(CDepth1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeCDepth1 = createClassComponent("randomname");
const found = findNodeByComponent(rootNode, FakeCDepth1);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for 2nd-level class with same component name", () => {
class C1 extends React.Component {
render() {
return <C2 />;
}
}
class C2 extends React.Component {
render() {
return <div>C2 here</div>;
}
}
const WrappedC = getWrappedComponent(C1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeC2 = createClassComponent(C2.name);
const found = findNodeByComponent(rootNode, FakeC2);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for 2nd-level class with different component name", () => {
class C1 extends React.Component {
render() {
return <C2 />;
}
}
class C2 extends React.Component {
render() {
return <div>C2 here</div>;
}
}
const WrappedC = getWrappedComponent(C1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeC2 = createClassComponent("randomName");
const found = findNodeByComponent(rootNode, FakeC2);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for top-level function with same function name", () => {
const WrappedC = getWrappedComponent(FnDepth1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeFnDepth1 = createClassComponent(FnDepth1.name);
const found = findNodeByComponent(rootNode, FakeFnDepth1);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for top-level function with different function name", () => {
const WrappedC = getWrappedComponent(FnDepth1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeFnDepth1 = createClassComponent("randomName");
const found = findNodeByComponent(rootNode, FakeFnDepth1);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for 2nd-level function with same function name", () => {
function Fn1() {
return <Fn2 />;
}
function Fn2() {
return <div>Fn2 here</div>;
}
const WrappedC = getWrappedComponent(Fn1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeFn2 = createClassComponent(Fn2.name);
const found = findNodeByComponent(rootNode, FakeFn2);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for 2nd-level function with different function name", () => {
function Fn1() {
return <Fn2 />;
}
function Fn2() {
return <div>Fn2 here</div>;
}
const WrappedC = getWrappedComponent(Fn1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeFn2 = createClassComponent("randomName");
const found = findNodeByComponent(rootNode, FakeFn2);
expect(found).toBeFalsy();
expect(found).toBe(null);
});
it("should not work for 5th-level function with same or diff fn name", () => {
function Fn1() {
return (
<div>
<div>
<span></span>
<Fn2></Fn2>
</div>
</div>
);
}
function Fn2() {
return <a href="google.com">Fn2 here</a>;
}
const WrappedC = getWrappedComponent(Fn1);
const rootNode = mountAndGetRootNode(WrappedC, container);
const FakeFn2Same = createClassComponent(Fn2.name);
const FakeFn2Diff = createClassComponent("randomname");
const foundSame = findNodeByComponent(rootNode, FakeFn2Same);
const foundDiff = findNodeByComponent(rootNode, FakeFn2Diff);
expect(foundSame).toBeFalsy();
expect(foundSame).toBe(null);
expect(foundDiff).toBeFalsy();
expect(foundDiff).toBe(null);
});
});
});
@@ -0,0 +1,95 @@
import * as React from "react";
// Import stuff from src
import { findNodeByComponentRef } from "../src";
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import getWrappedComponent from "./utils/getWrappedComponent";
class RandomClass extends React.Component {
render() {
return <div></div>;
}
}
// Import test helpers and sample components
describe("findNodeByComponentRef", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("negative", () => {
it("should not work for 2nd-level class", () => {
const C2Ref = React.createRef<C2>();
class C1 extends React.Component {
render() {
return <C2 ref={C2Ref} />;
}
}
class C2 extends React.Component {
render() {
return <div>C2 here</div>;
}
}
const WrappedC = getWrappedComponent(C1);
const rootNode = mountAndGetRootNode(WrappedC, container);
if (C2Ref.current === null) {
throw new Error("Ref is not yet set");
}
const foundSame = findNodeByComponentRef(rootNode, new C2({}));
const foundDiff = findNodeByComponentRef(rootNode, new RandomClass({}));
expect(foundSame).toBeFalsy();
expect(foundSame).toBe(null);
expect(foundDiff).toBeFalsy();
expect(foundDiff).toBe(null);
});
it("should work for 5th-level class", () => {
const C2Ref = React.createRef<C2>();
class C1 extends React.Component {
render() {
return (
<div>
<div>
<span></span>
<C2 ref={C2Ref}></C2>
</div>
</div>
);
}
}
class C2 extends React.Component {
render() {
return <a href="google.com">Fn2 here</a>;
}
}
const WrappedC = getWrappedComponent(C1);
const rootNode = mountAndGetRootNode(WrappedC, container);
if (C2Ref.current === null) {
throw new Error("Ref is not yet set");
}
const foundSame = findNodeByComponentRef(rootNode, new C2({}));
const foundDiff = findNodeByComponentRef(rootNode, new RandomClass({}));
expect(foundSame).toBeFalsy();
expect(foundSame).toBe(null);
expect(foundDiff).toBeFalsy();
expect(foundDiff).toBe(null);
});
});
});
+1 -1
View File
@@ -26,7 +26,7 @@ describe("traverseGenerator", () => {
document.body.removeChild(container);
});
describe("basic", () => {
describe("ordered", () => {
it("order doesn't matter for 1 node if self is present - case 1", () => {
const rootNode = mountAndGetRootNode(CDepth1, container);
+143
View File
@@ -0,0 +1,143 @@
import * as React from "react";
// Import stuff from src
import { FiberNodeForComponentClass, FiberNode } from "../src/mocked-types";
import { traverseGenerator } from "../src";
// Import test helpers and sample components
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import {
createClassComponents
// createFunctionComponents
} from "./utils/createComponent";
describe("traverseGenerator", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("skipped", () => {
it("should traverse just top-level with skipChild", () => {
const [C2, C3, C4, C5] = createClassComponents(["C2", "C3", "C4", "C5"]);
class C1 extends React.Component {
render() {
return (
<React.Fragment>
<C2>
<C3 />
</C2>
<C4>
<C5 />
</C4>
</React.Fragment>
);
}
}
const rootNode = mountAndGetRootNode(C1, container);
const nodeIterator = traverseGenerator(rootNode);
// Consume generator
let nodes: Array<FiberNode> = [];
const genArgs = { skipChild: true };
for (
let result = nodeIterator.next();
!result.done;
result = nodeIterator.next(genArgs)
) {
const currentNode = result.value;
nodes.push(currentNode);
}
expect(nodes.length).toBe(1);
expect(
nodes.map(tmpNode => (tmpNode as FiberNodeForComponentClass).type)
).toEqual([C1]);
});
it("should traverse just first 2 levels with inner skipChild", () => {
const [C2, C3, C4, C5] = createClassComponents(["C2", "C3", "C4", "C5"]);
class C1 extends React.Component {
render() {
return (
<React.Fragment>
<C2>
<C3 />
</C2>
<C4>
<C5 />
</C4>
</React.Fragment>
);
}
}
const rootNode = mountAndGetRootNode(C1, container);
const nodeIterator = traverseGenerator(rootNode);
// Consume generator
let nodes: Array<FiberNode> = [];
const genArgs = { skipChild: true };
for (
let result = nodeIterator.next();
!result.done;
result = nodeIterator.next(nodes.length > 1 ? genArgs : undefined)
) {
const currentNode = result.value;
nodes.push(currentNode);
}
expect(nodes.length).toBe(3);
expect(
nodes.map(tmpNode => (tmpNode as FiberNodeForComponentClass).type)
).toEqual([C1, C2, C4]);
});
it("should traverse one branch correctly with skipSibling", () => {
const [C2, C3, C4, C5] = createClassComponents(["C2", "C3", "C4", "C5"]);
class C1 extends React.Component {
render() {
return (
<React.Fragment>
<C2>
<C3 />
</C2>
<C4>
<C5 />
</C4>
</React.Fragment>
);
}
}
const rootNode = mountAndGetRootNode(C1, container);
const nodeIterator = traverseGenerator(rootNode);
// Consume generator
let nodes: Array<FiberNode> = [];
const genArgs = { skipSibling: true };
for (
let result = nodeIterator.next();
!result.done;
result = nodeIterator.next(genArgs)
) {
const currentNode = result.value;
nodes.push(currentNode);
}
expect(nodes.length).toBe(3);
expect(
nodes.map(tmpNode => (tmpNode as FiberNodeForComponentClass).type)
).toEqual([C1, C2, C3]);
});
});
});
@@ -0,0 +1,77 @@
// import * as React from "react";
// Import stuff from src
import { doesElementContainRootFiberNode } from "../src/utils";
// Import test helpers and sample components
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import { createFunctionComponent } from "./utils/createComponent";
describe("traverse", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
try {
document.body.removeChild(container);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
}
});
describe("doesElementContainRootFiberNode", () => {
it("should work for direct element", () => {
const fn1 = createFunctionComponent("fn1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(fn1, containerInner);
const resultPositive = doesElementContainRootFiberNode(containerInner);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should not work for parent element", () => {
const fn1 = createFunctionComponent("fn1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(fn1, containerInner);
const resultNegative = doesElementContainRootFiberNode(container);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for child element", () => {
const fn1 = createFunctionComponent("fn1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(fn1, container);
const resultNegative = doesElementContainRootFiberNode(containerInner);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should work for body", () => {
const fn1 = createFunctionComponent("fn1");
mountAndGetRootNode(fn1, document.body);
const resultPositive = doesElementContainRootFiberNode(document.body);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
});
});
@@ -0,0 +1,94 @@
// import * as React from "react";
// Import stuff from src
import { getRootFiberNodeFromDOM } from "../src/utils";
// Import test helpers and sample components
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import { createClassComponent } from "./utils/createComponent";
describe("traverse", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
try {
document.body.removeChild(container);
} catch (error) {
if (!(error instanceof DOMException)) {
throw error;
}
}
});
describe("getRootFiberNodeFromDOM", () => {
it("should work for direct element", () => {
const C1 = createClassComponent("C1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(C1, containerInner);
const resultPositive = getRootFiberNodeFromDOM(containerInner);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).not.toBe(null);
expect((resultPositive as any).child.child.type).toBe(C1);
});
it("should work for parent element", () => {
const C1 = createClassComponent("C1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(C1, containerInner);
const resultPositive = getRootFiberNodeFromDOM(container);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).not.toBe(null);
expect((resultPositive as any).child.child.type).toBe(C1);
});
it("should work without any element - default args", () => {
const C1 = createClassComponent("C1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(C1, containerInner);
const resultPositive = getRootFiberNodeFromDOM();
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).not.toBe(null);
expect((resultPositive as any).child.child.type).toBe(C1);
});
it("should not work for child element", () => {
const C1 = createClassComponent("C1");
const containerInner = container.appendChild(
document.createElement("span")
);
mountAndGetRootNode(C1, container);
const resultNegative = getRootFiberNodeFromDOM(containerInner);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(null);
});
it("should work for body", () => {
const C1 = createClassComponent("C1");
mountAndGetRootNode(C1, document.body);
const resultPositive = getRootFiberNodeFromDOM(document.body);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).not.toBe(null);
expect((resultPositive as any).child.child.type).toBe(C1);
});
});
});
@@ -0,0 +1,74 @@
// import * as React from "react";
// Import stuff from src
import { isConstructorComponentClass } from "../src/utils";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isConstructorComponentClass", () => {
it("should work for class components", () => {
const C1 = createClassComponent("C1");
const resultPositive = isConstructorComponentClass(C1);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should not work for any class", () => {
const C1 = class {};
const resultNegative = isConstructorComponentClass(C1 as any);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for any function", () => {
const fn1 = function() {};
const resultNegative = isConstructorComponentClass(fn1 as any);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for function components", () => {
const fn1 = createFunctionComponent();
const resultNegative = isConstructorComponentClass(fn1);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for string", () => {
const resultNegative = isConstructorComponentClass("div");
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for null", () => {
const resultNegative = isConstructorComponentClass(null);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
});
});
@@ -0,0 +1,74 @@
// import * as React from "react";
// Import stuff from src
import { isConstructorFunctionComponent } from "../src/utils";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isConstructorFunctionComponent", () => {
it("should work for any function - current limitation", () => {
const fn1 = function() {};
const resultPositive = isConstructorFunctionComponent(fn1 as any);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should work for function components", () => {
const fn1 = createFunctionComponent();
const resultPositive = isConstructorFunctionComponent(fn1);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should not work for string", () => {
const resultNegative = isConstructorFunctionComponent("div");
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for null", () => {
const resultNegative = isConstructorFunctionComponent(null);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should work for any class - current limitation", () => {
const C1 = class {};
const resultPositive = isConstructorFunctionComponent(C1 as any);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should not work for class components", () => {
const C1 = createClassComponent("C1");
const resultNegative = isConstructorFunctionComponent(C1);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
});
});
+74
View File
@@ -0,0 +1,74 @@
// import * as React from "react";
// Import stuff from src
import { isConstructorHtmlLike } from "../src/utils";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isConstructorHtmlLike", () => {
it("should work for string", () => {
const resultPositive = isConstructorHtmlLike("div");
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should work for null", () => {
const resultPositive = isConstructorHtmlLike(null);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
});
it("should not work for any function", () => {
const fn1 = function() {};
const resultNegative = isConstructorHtmlLike(fn1 as any);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for function components", () => {
const fn1 = createFunctionComponent();
const resultNegative = isConstructorHtmlLike(fn1);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for any class", () => {
const C1 = class {};
const resultNegative = isConstructorHtmlLike(C1 as any);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for class components", () => {
const C1 = createClassComponent("C1");
const resultNegative = isConstructorHtmlLike(C1);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
});
});
+63
View File
@@ -0,0 +1,63 @@
// import * as React from "react";
// Import stuff from src
import { isNodeComponentClass } from "../src/utils";
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isNodeComponentClass", () => {
it("should work for class component", () => {
const C1 = createClassComponent("C1");
const rootNode = mountAndGetRootNode(C1, container);
const result = isNodeComponentClass(rootNode);
expect(result).not.toBeFalsy();
expect(result).toBe(true);
});
it("should not work for function component", () => {
const fn1 = createFunctionComponent("fn1");
const rootNode = mountAndGetRootNode(fn1, container);
const result = isNodeComponentClass(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
it("should not work for html like component - div", () => {
const rootNode = mountAndGetRootNode("div", container);
const result = isNodeComponentClass(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
it("should not work for html like component - svg", () => {
const rootNode = mountAndGetRootNode("svg", container);
const result = isNodeComponentClass(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
});
});
@@ -0,0 +1,63 @@
// import * as React from "react";
// Import stuff from src
import { isNodeFunctionComponent } from "../src/utils";
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isNodeFunctionComponent", () => {
it("should work for function component", () => {
const fn1 = createFunctionComponent("fn1");
const rootNode = mountAndGetRootNode(fn1, container);
const result = isNodeFunctionComponent(rootNode);
expect(result).not.toBeFalsy();
expect(result).toBe(true);
});
it("should not work for class component", () => {
const C1 = createClassComponent("C1");
const rootNode = mountAndGetRootNode(C1, container);
const result = isNodeFunctionComponent(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
it("should not work for html like component - div", () => {
const rootNode = mountAndGetRootNode("div", container);
const result = isNodeFunctionComponent(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
it("should work for html like component - svg", () => {
const rootNode = mountAndGetRootNode("svg", container);
const result = isNodeFunctionComponent(rootNode);
expect(result).toBeFalsy();
expect(result).toBe(false);
});
});
});
+102
View File
@@ -0,0 +1,102 @@
import * as React from "react";
// Import stuff from src
import { isNodeHtmlLike, isNodeNotHtmlLike } from "../src/utils";
import { mountAndGetRootNode } from "./utils/mountInEnzyme";
import { FiberNodeForInstrinsicElement } from "../src/mocked-types";
import {
createFunctionComponent,
createClassComponent
} from "./utils/createComponent";
// Import test helpers and sample components
describe("utils", () => {
let container: HTMLDivElement;
beforeEach(() => {
container = document.body.appendChild(document.createElement("div"));
});
afterEach(() => {
document.body.removeChild(container);
});
describe("isNodeHtmlLike", () => {
it("should work for div", () => {
const rootNode = mountAndGetRootNode("div", container);
const resultPositive = isNodeHtmlLike(rootNode);
const resultNegative = isNodeNotHtmlLike(rootNode);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should work for svg root element", () => {
const rootNode = mountAndGetRootNode("svg", container);
const resultPositive = isNodeHtmlLike(rootNode);
const resultNegative = isNodeNotHtmlLike(rootNode);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should work for svg inner elements", () => {
function SomeSVG() {
return (
<svg>
<circle cx={5} />
</svg>
);
}
const rootNode = mountAndGetRootNode(SomeSVG, container);
expect(isNodeHtmlLike(rootNode)).toBeFalsy();
const circleNode = (rootNode.child as FiberNodeForInstrinsicElement)
.child as FiberNodeForInstrinsicElement;
expect(circleNode).not.toBe(null);
expect(circleNode.type).toBe("circle");
const resultPositive = isNodeHtmlLike(circleNode);
const resultNegative = isNodeNotHtmlLike(circleNode);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for function component", () => {
const fn1 = createFunctionComponent("fn1");
const rootNode = mountAndGetRootNode(fn1, container);
const resultPositive = isNodeNotHtmlLike(rootNode);
const resultNegative = isNodeHtmlLike(rootNode);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
it("should not work for class component", () => {
const C1 = createClassComponent("C1");
const rootNode = mountAndGetRootNode(C1, container);
const resultPositive = isNodeNotHtmlLike(rootNode);
const resultNegative = isNodeHtmlLike(rootNode);
expect(resultPositive).not.toBeFalsy();
expect(resultPositive).toBe(true);
expect(resultNegative).toBeFalsy();
expect(resultNegative).toBe(false);
});
});
});
+5 -5
View File
@@ -1,7 +1,7 @@
import * as React from "react";
import { mount } from "enzyme";
import { FiberNode, FiberNodeForComponentClass } from "../../src/mocked-types";
import { isConstructorFunctionComponent } from "../../src/utils";
import { isConstructorComponentClass } from "../../src/utils";
import getWrappedComponent from "./getWrappedComponent";
export class RootNodeNotFoundError extends Error {
@@ -13,14 +13,14 @@ export class RootNodeNotFoundError extends Error {
}
export function mountAndGetRootNode(
SomeComponent: React.ComponentType,
SomeComponent: React.ElementType,
container: HTMLElement
): FiberNode {
const rootRef = React.createRef<React.Component>();
let ToMount = undefined;
let ToMount: React.ComponentClass | undefined = undefined;
// Wrap function components in ComponentClass to be able to set ref
if (isConstructorFunctionComponent(SomeComponent)) {
if (!isConstructorComponentClass(SomeComponent)) {
ToMount = getWrappedComponent(SomeComponent);
} else {
ToMount = SomeComponent;
@@ -41,7 +41,7 @@ export function mountAndGetRootNode(
}
// Unwrap function components to return expected root node
if (isConstructorFunctionComponent(SomeComponent)) {
if (!isConstructorComponentClass(SomeComponent)) {
return (rootNode as FiberNodeForComponentClass).child as FiberNode;
} else {
return rootNode;