From 64e583921eaf46c1f2a1e9b43f5cd3d237095311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gytis=20=C5=A0k?= Date: Tue, 16 Aug 2016 16:36:41 +0300 Subject: [PATCH 01/57] Add missing import statement in Mocha example --- docs/guides/mocha.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/guides/mocha.md b/docs/guides/mocha.md index 30fe94f9e..f0eabf8d9 100644 --- a/docs/guides/mocha.md +++ b/docs/guides/mocha.md @@ -9,6 +9,7 @@ npm i --save-dev enzyme ```jsx import React from 'react'; +import { expect } from 'chai'; import { mount, shallow } from 'enzyme'; describe('', () => { From 02059d2acded1438af29dd2cf7e0ca832438ab9f Mon Sep 17 00:00:00 2001 From: Bradley C Bailey Date: Thu, 18 Aug 2016 10:59:41 -0600 Subject: [PATCH 02/57] GoDaddy in the wild --- INTHEWILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/INTHEWILD.md b/INTHEWILD.md index 53e0ba21f..f7df9c11f 100644 --- a/INTHEWILD.md +++ b/INTHEWILD.md @@ -10,6 +10,7 @@ Organizations - [Hudl](http://hudl.github.io/) - [NET-A-PORTER](https://github.com/NET-A-PORTER) - [Rangle.io](https://github.com/rangle) + - [GoDaddy](https://github.com/godaddy) Projects ---------- From c522b50cfad574c0127c6e0aa099fe83f0855888 Mon Sep 17 00:00:00 2001 From: Maja Wichrowska Date: Thu, 18 Aug 2016 10:47:08 -0700 Subject: [PATCH 03/57] react-dates in the wild Adds `react-dates` as one of the projects that uses Enzyme. --- INTHEWILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/INTHEWILD.md b/INTHEWILD.md index f7df9c11f..e21b3d29a 100644 --- a/INTHEWILD.md +++ b/INTHEWILD.md @@ -19,3 +19,4 @@ Projects - [Reactstrap](https://github.com/reactstrap/reactstrap) - [Recompose](https://github.com/acdlite/recompose) - [Reapop](https://github.com/LouisBarranqueiro/reapop) + - [React Dates](https://github.com/airbnb/react-dates) From 2535905281bdc713b826ec13c7b219a9e8100c0f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 18 Aug 2016 21:56:46 -0700 Subject: [PATCH 04/57] [Deps] update `lodash` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c75c52346..37699c081 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "dependencies": { "cheerio": "^0.20.0", "is-subset": "^0.1.1", - "lodash": "^4.14.1", + "lodash": "^4.15.0", "object-is": "^1.0.1", "object.assign": "^4.0.4", "object.values": "^1.0.3" From 68111e5f5bb9b032263337a798fb8ee3f4845ecf Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Thu, 18 Aug 2016 21:58:10 -0700 Subject: [PATCH 05/57] [Dev Deps] update `eslint`, `eslint-config-airbnb`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `mocha` --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 37699c081..27bea3973 100644 --- a/package.json +++ b/package.json @@ -71,19 +71,19 @@ "enzyme-example-karma-webpack": "^0.1.4", "enzyme-example-mocha": "^0.1.0", "enzyme-example-react-native": "^0.1.0", - "eslint": "^3.2.2", - "eslint-config-airbnb": "^10.0.0", - "eslint-plugin-import": "^1.12.0", - "eslint-plugin-jsx-a11y": "^2.0.1", - "eslint-plugin-react": "^6.0.0", + "eslint": "^3.3.1", + "eslint-config-airbnb": "^10.0.1", + "eslint-plugin-import": "^1.13.0", + "eslint-plugin-jsx-a11y": "^2.1.0", + "eslint-plugin-react": "^6.1.2", "gitbook-cli": "^1.0.1", "istanbul": "^1.0.0-alpha.2", "jsdom": "^6.1.0", - "mocha": "^3.0.1", + "mocha": "^3.0.2", "rimraf": "^2.5.4", "sinon": "^1.17.5" }, "peerDependencies": { - "react": "0.13.x || 0.14.x || ^15.0.0-0" + "react": "0.13.x || 0.14.x || ^15.0.0-0 || 15.x" } } From 1add055ce7263cd1261f82c9c2440d198e9efaa4 Mon Sep 17 00:00:00 2001 From: "Anders D. Johnson" Date: Fri, 19 Aug 2016 23:10:56 -0500 Subject: [PATCH 06/57] [Docs] fix typos in README --- docs/api/mount.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/mount.md b/docs/api/mount.md index 3986881fb..f1eebb1b0 100644 --- a/docs/api/mount.md +++ b/docs/api/mount.md @@ -1,7 +1,7 @@ # Full Rendering API (`mount(...)`) -Full DOM rendering is ideal for use cases where you have components that may interact with DOM apis, -or may require the full lifecycle in order to fully test the component (ie, `componentDidMount` +Full DOM rendering is ideal for use cases where you have components that may interact with DOM APIs, +or may require the full lifecycle in order to fully test the component (i.e., `componentDidMount` etc.) Full DOM rendering requires that a full DOM API be available at the global scope. This means that From 9148f4a7f2b70218b0059ff16e3b0d63d5eddc2a Mon Sep 17 00:00:00 2001 From: Ben Ilegbodu Date: Sat, 20 Aug 2016 15:33:22 -0700 Subject: [PATCH 07/57] Fix broken links to API docs - The link to `.someWhere` in mount.md was broken due to a capitalization error - All of the other links were broken in the web version of the docs due to absolute paths --- docs/api/mount.md | 14 +++++++------- docs/api/shallow.md | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/api/mount.md b/docs/api/mount.md index f1eebb1b0..d0254f091 100644 --- a/docs/api/mount.md +++ b/docs/api/mount.md @@ -186,28 +186,28 @@ Maps the current array of nodes to another array. #### [`.matchesElement(node) => Boolean`](ReactWrapper/matchesElement.md) Returns whether or not a given react element matches the current render tree. -#### [`.reduce(fn[, initialValue]) => Any`](/docs/api/ReactWrapper/reduce.md) +#### [`.reduce(fn[, initialValue]) => Any`](ReactWrapper/reduce.md) Reduces the current array of nodes to a value -#### [`.reduceRight(fn[, initialValue]) => Any`](/docs/api/ReactWrapper/reduceRight.md) +#### [`.reduceRight(fn[, initialValue]) => Any`](ReactWrapper/reduceRight.md) Reduces the current array of nodes to a value, from right to left. #### [`.tap(intercepter) => Self`](ReactWrapper/tap.md) Taps into the wrapper method chain. Helpful for debugging. -#### [`.some(selector) => Boolean`](/docs/api/ReactWrapper/some.md) +#### [`.some(selector) => Boolean`](ReactWrapper/some.md) Returns whether or not any of the nodes in the wrapper match the provided selector. -#### [`.someWhere(predicate) => Boolean`](/docs/api/ReactWrapper/someWHere.md) +#### [`.someWhere(predicate) => Boolean`](ReactWrapper/someWhere.md) Returns whether or not any of the nodes in the wrapper pass the provided predicate function. -#### [`.every(selector) => Boolean`](/docs/api/ReactWrapper/every.md) +#### [`.every(selector) => Boolean`](ReactWrapper/every.md) Returns whether or not all of the nodes in the wrapper match the provided selector. -#### [`.everyWhere(predicate) => Boolean`](/docs/api/ReactWrapper/everyWhere.md) +#### [`.everyWhere(predicate) => Boolean`](ReactWrapper/everyWhere.md) Returns whether or not all of the nodes in the wrapper pass the provided predicate function. -#### [`.ref(refName) => ReactWrapper`](/docs/api/ReactWrapper/ref.md) +#### [`.ref(refName) => ReactWrapper`](ReactWrapper/ref.md) Returns a wrapper of the node that matches the provided reference name. #### [`.detach() => void`](ReactWrapper/detach.md) diff --git a/docs/api/shallow.md b/docs/api/shallow.md index a67d2694d..f9468739d 100644 --- a/docs/api/shallow.md +++ b/docs/api/shallow.md @@ -187,23 +187,23 @@ Iterates through each node of the current wrapper and executes the provided func #### [`.map(fn) => Array`](ShallowWrapper/map.md) Maps the current array of nodes to another array. -#### [`.reduce(fn[, initialValue]) => Any`](/docs/api/ShallowWrapper/reduce.md) +#### [`.reduce(fn[, initialValue]) => Any`](ShallowWrapper/reduce.md) Reduces the current array of nodes to a value -#### [`.reduceRight(fn[, initialValue]) => Any`](/docs/api/ShallowWrapper/reduceRight.md) +#### [`.reduceRight(fn[, initialValue]) => Any`](ShallowWrapper/reduceRight.md) Reduces the current array of nodes to a value, from right to left. #### [`.tap(intercepter) => Self`](ShallowWrapper/tap.md) Taps into the wrapper method chain. Helpful for debugging. -#### [`.some(selector) => Boolean`](/docs/api/ShallowWrapper/some.md) +#### [`.some(selector) => Boolean`](ShallowWrapper/some.md) Returns whether or not any of the nodes in the wrapper match the provided selector. -#### [`.someWhere(predicate) => Boolean`](/docs/api/ShallowWrapper/someWhere.md) +#### [`.someWhere(predicate) => Boolean`](ShallowWrapper/someWhere.md) Returns whether or not any of the nodes in the wrapper pass the provided predicate function. -#### [`.every(selector) => Boolean`](/docs/api/ShallowWrapper/every.md) +#### [`.every(selector) => Boolean`](ShallowWrapper/every.md) Returns whether or not all of the nodes in the wrapper match the provided selector. -#### [`.everyWhere(predicate) => Boolean`](/docs/api/ShallowWrapper/everyWhere.md) +#### [`.everyWhere(predicate) => Boolean`](ShallowWrapper/everyWhere.md) Returns whether or not all of the nodes in the wrapper pass the provided predicate function. From e5cb263723a0b36ac74822777cda53a9ccee3db3 Mon Sep 17 00:00:00 2001 From: Nick Italiano Date: Thu, 25 Aug 2016 13:16:36 -0700 Subject: [PATCH 08/57] Added Airware to organization list --- INTHEWILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/INTHEWILD.md b/INTHEWILD.md index e21b3d29a..aa9a1f383 100644 --- a/INTHEWILD.md +++ b/INTHEWILD.md @@ -11,6 +11,7 @@ Organizations - [NET-A-PORTER](https://github.com/NET-A-PORTER) - [Rangle.io](https://github.com/rangle) - [GoDaddy](https://github.com/godaddy) + - [Airware](https://github.com/airware) Projects ---------- From 2aaa85b63eb09e85f83ba43b677bd6603689769f Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Aug 2016 15:45:20 -0700 Subject: [PATCH 09/57] [Fix] zero is a falsy but valid propValue. Fixes #562. --- src/MountedTraversal.js | 2 +- src/ShallowTraversal.js | 2 +- test/ShallowTraversal-spec.jsx | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/MountedTraversal.js b/src/MountedTraversal.js index 7b1f9da95..649cec776 100644 --- a/src/MountedTraversal.js +++ b/src/MountedTraversal.js @@ -100,7 +100,7 @@ export function instHasProperty(inst, propKey, stringifiedPropValue) { return false; } - if (propValue) { + if (propValue || propValue === 0) { return nodePropValue === propValue; } diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index e12608428..3975af8e3 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -97,7 +97,7 @@ export function nodeHasProperty(node, propKey, stringifiedPropValue) { return false; } - if (propValue) { + if (propValue || propValue === 0) { return nodePropValue === propValue; } diff --git a/test/ShallowTraversal-spec.jsx b/test/ShallowTraversal-spec.jsx index f31eed347..c7e95cc4f 100644 --- a/test/ShallowTraversal-spec.jsx +++ b/test/ShallowTraversal-spec.jsx @@ -110,6 +110,10 @@ describe('ShallowTraversal', () => { expect(nodeHasProperty(
, 'foo', '2e8')).to.equal(true); expect(nodeHasProperty(
, 'foo', 'Infinity')).to.equal(true); expect(nodeHasProperty(
, 'foo', '-Infinity')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '0')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '-0')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '0')).to.equal(false); + expect(nodeHasProperty(
, 'foo', '-0')).to.equal(false); }); it('should throw when un unquoted string is passed in', () => { From eba4d068839cc2d2d07c40d074c011283756ba2a Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Aug 2016 15:45:46 -0700 Subject: [PATCH 10/57] =?UTF-8?q?[Refactor]=20use=20ShallowTraversal?= =?UTF-8?q?=E2=80=99s=20`nodeHasProperty`=20inside=20MountedTraversal?= =?UTF-8?q?=E2=80=99s=20`instHasProperty`.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MountedTraversal.js | 24 +++++------------------- src/ShallowTraversal.js | 3 ++- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/MountedTraversal.js b/src/MountedTraversal.js index 649cec776..aa096f610 100644 --- a/src/MountedTraversal.js +++ b/src/MountedTraversal.js @@ -2,7 +2,6 @@ import isEmpty from 'lodash/isEmpty'; import isSubset from 'is-subset'; import { internalInstance, - coercePropValue, nodeEqual, propsOfNode, isFunctionalComponent, @@ -13,6 +12,9 @@ import { SELECTOR, nodeHasType, } from './Utils'; +import { + nodeHasProperty, +} from './ShallowTraversal'; import { isDOMComponent, isCompositeComponent, @@ -85,26 +87,10 @@ export function instHasType(inst, type) { export function instHasProperty(inst, propKey, stringifiedPropValue) { if (!isDOMComponent(inst)) return false; - const node = getNode(inst); - const nodeProps = propsOfNode(node); - const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey); - if (descriptor && descriptor.get) { - return false; - } - const nodePropValue = nodeProps[propKey]; - - const propValue = coercePropValue(propKey, stringifiedPropValue); - // intentionally not matching node props that are undefined - if (nodePropValue === undefined) { - return false; - } - - if (propValue || propValue === 0) { - return nodePropValue === propValue; - } + const node = getNode(inst); - return Object.prototype.hasOwnProperty.call(nodeProps, propKey); + return nodeHasProperty(node, propKey, stringifiedPropValue); } // called with private inst diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index 3975af8e3..f97dd0b6a 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -86,13 +86,14 @@ export function nodeHasId(node, id) { export function nodeHasProperty(node, propKey, stringifiedPropValue) { const nodeProps = propsOfNode(node); - const propValue = coercePropValue(propKey, stringifiedPropValue); const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey); if (descriptor && descriptor.get) { return false; } const nodePropValue = nodeProps[propKey]; + const propValue = coercePropValue(propKey, stringifiedPropValue); + if (nodePropValue === undefined) { return false; } From b6e82f48378dd5e746300cd5cec71454c362eeaa Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Aug 2016 16:11:44 -0700 Subject: [PATCH 11/57] [Tests] speed up tests further by *really* only running linting once. - Also, simplify test matrix config. --- .travis.yml | 67 ++++++++++++++--------------------------------------- 1 file changed, 17 insertions(+), 50 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8eaf0f057..36462beaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,59 +10,26 @@ before_install: - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then npm install -g npm; fi' before_script: "sh install-relevant-react.sh" script: - - 'if [ -z "$REACT" ] && [ "${TRAVIS_NODE_VERSION}" = "4" ]; then npm run test:env -- "${EXAMPLE}" ; elif [ -z "$REACT" ]; then echo "Test Skipped" ; elif [ "${TRAVIS_NODE_VERSION}" = "4" ]; then npm run lint && npm run travis ; elif [ "${TRAVIS_NODE_VERSION}" = "0.12" ] || [ "${TRAVIS_NODE_VERSION}" = "0.10" ]; then npm run travis ; else npm test ; fi' + - 'if [ -n "${EXAMPLE-}" ]; then npm run test:env -- "${EXAMPLE}" ; elif [ -n "${LINT-}" ]; then npm run lint; elif [ -n "${REACT-}" ]; then npm run travis; else echo "Test Skipped" ; fi' after_script: - 'if [ "${TRAVIS_NODE_VERSION}" = "4" ] || [ "${TRAVIS_NODE_VERSION}" = "0.12" ]; then cat ./coverage/lcov.info | ./node_modules/.bin/coveralls ; fi' +sudo: false +matrix: + fast_finish: true + include: + - node_js: "node" + env: LINT=true + - node_js: "node" + env: EXAMPLE=mocha + - node_js: "node" + env: EXAMPLE=karma + - node_js: "node" + env: EXAMPLE=react-native + - node_js: "node" + env: EXAMPLE=karma-webpack + - node_js: "node" + env: EXAMPLE=jest env: - REACT=0.13 - REACT=0.14 - REACT=15 - - EXAMPLE=mocha - - EXAMPLE=karma - - EXAMPLE=react-native - - EXAMPLE=karma-webpack - - EXAMPLE=jest -sudo: false -matrix: - fast_finish: true - exclude: - - node_js: "5" - env: EXAMPLE=mocha - - node_js: "5" - env: EXAMPLE=karma - - node_js: "5" - env: EXAMPLE=react-native - - node_js: "5" - env: EXAMPLE=karma-webpack - - node_js: "5" - env: EXAMPLE=jest - - node_js: "4" - env: EXAMPLE=mocha - - node_js: "4" - env: EXAMPLE=karma - - node_js: "4" - env: EXAMPLE=react-native - - node_js: "4" - env: EXAMPLE=karma-webpack - - node_js: "4" - env: EXAMPLE=jest - - node_js: "0.12" - env: EXAMPLE=mocha - - node_js: "0.12" - env: EXAMPLE=karma - - node_js: "0.12" - env: EXAMPLE=react-native - - node_js: "0.12" - env: EXAMPLE=karma-webpack - - node_js: "0.12" - env: EXAMPLE=jest - - node_js: "0.10" - env: EXAMPLE=mocha - - node_js: "0.10" - env: EXAMPLE=karma - - node_js: "0.10" - env: EXAMPLE=react-native - - node_js: "0.10" - env: EXAMPLE=karma-webpack - - node_js: "0.10" - env: EXAMPLE=jest From 3ecc89b4415bbd2d9e762faaa1689367e668dcf8 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Aug 2016 17:36:55 -0700 Subject: [PATCH 12/57] [Tests] react-native and karma-webpack example builds fail currently --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index 36462beaf..af2e6cd81 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,11 @@ matrix: env: EXAMPLE=karma-webpack - node_js: "node" env: EXAMPLE=jest + allow_failures: + - node_js: "node" + env: EXAMPLE=react-native + - node_js: "node" + env: EXAMPLE=karma-webpack env: - REACT=0.13 - REACT=0.14 From 404160e623b77855514f39cebd4358e2705eea4c Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 27 Aug 2016 09:36:27 -0700 Subject: [PATCH 13/57] [Fix] empty strings are also valid propValues. --- src/ShallowTraversal.js | 2 +- src/Utils.js | 5 +++++ test/ShallowTraversal-spec.jsx | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index f97dd0b6a..fe7b8099e 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -98,7 +98,7 @@ export function nodeHasProperty(node, propKey, stringifiedPropValue) { return false; } - if (propValue || propValue === 0) { + if (propValue || propValue === 0 || propValue === '') { return nodePropValue === propValue; } diff --git a/src/Utils.js b/src/Utils.js index 95e31595e..a8f151ca9 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -213,6 +213,11 @@ export function coercePropValue(propName, propValue) { return propValue; } + // can be the empty string + if (propValue === '') { + return propValue; + } + const trimmedValue = propValue.trim(); // if propValue includes quotes, it should be diff --git a/test/ShallowTraversal-spec.jsx b/test/ShallowTraversal-spec.jsx index c7e95cc4f..de0d5cace 100644 --- a/test/ShallowTraversal-spec.jsx +++ b/test/ShallowTraversal-spec.jsx @@ -110,12 +110,22 @@ describe('ShallowTraversal', () => { expect(nodeHasProperty(
, 'foo', '2e8')).to.equal(true); expect(nodeHasProperty(
, 'foo', 'Infinity')).to.equal(true); expect(nodeHasProperty(
, 'foo', '-Infinity')).to.equal(true); + }); + + it('should parse zeroes properly', () => { expect(nodeHasProperty(
, 'foo', '0')).to.equal(true); expect(nodeHasProperty(
, 'foo', '-0')).to.equal(true); expect(nodeHasProperty(
, 'foo', '0')).to.equal(false); expect(nodeHasProperty(
, 'foo', '-0')).to.equal(false); }); + it('should work with empty strings', () => { + expect(nodeHasProperty(
, 'foo', '')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '""')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '')).to.equal(false); + expect(nodeHasProperty(
, 'foo', '""')).to.equal(false); + }); + it('should throw when un unquoted string is passed in', () => { const node = (
); From 659a829f4f52ad8d1ef316178255dc7c568fe324 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 27 Aug 2016 09:49:39 -0700 Subject: [PATCH 14/57] [Fix] `NaN` is also a valid propValue --- src/ShallowTraversal.js | 5 +++-- src/Utils.js | 6 +++++- test/ShallowTraversal-spec.jsx | 5 +++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index fe7b8099e..97f03d2fe 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -1,6 +1,7 @@ import React from 'react'; import isEmpty from 'lodash/isEmpty'; import isSubset from 'is-subset'; +import is from 'object-is'; import { coercePropValue, propsOfNode, @@ -98,8 +99,8 @@ export function nodeHasProperty(node, propKey, stringifiedPropValue) { return false; } - if (propValue || propValue === 0 || propValue === '') { - return nodePropValue === propValue; + if (propValue || propValue === 0 || propValue === '' || is(NaN, propValue)) { + return is(nodePropValue, propValue); } return Object.prototype.hasOwnProperty.call(nodeProps, propKey); diff --git a/src/Utils.js b/src/Utils.js index a8f151ca9..ebf824a99 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -218,6 +218,10 @@ export function coercePropValue(propName, propValue) { return propValue; } + if (propValue === 'NaN') { + return NaN; + } + const trimmedValue = propValue.trim(); // if propValue includes quotes, it should be @@ -229,7 +233,7 @@ export function coercePropValue(propName, propValue) { const numericPropValue = +trimmedValue; // if parseInt is not NaN, then we've wanted a number - if (!isNaN(numericPropValue)) { + if (!is(NaN, numericPropValue)) { return numericPropValue; } diff --git a/test/ShallowTraversal-spec.jsx b/test/ShallowTraversal-spec.jsx index de0d5cace..390756819 100644 --- a/test/ShallowTraversal-spec.jsx +++ b/test/ShallowTraversal-spec.jsx @@ -126,6 +126,11 @@ describe('ShallowTraversal', () => { expect(nodeHasProperty(
, 'foo', '""')).to.equal(false); }); + it('should work with NaN', () => { + expect(nodeHasProperty(
, 'foo', 'NaN')).to.equal(true); + expect(nodeHasProperty(
, 'foo', 'NaN')).to.equal(false); + }); + it('should throw when un unquoted string is passed in', () => { const node = (
); From bcf1ee566f585159a99b12989a4eb6d9e138d74b Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sat, 27 Aug 2016 10:05:02 -0700 Subject: [PATCH 15/57] [Fix] `null` and `false` are also valid propValues --- src/ShallowTraversal.js | 2 +- src/Utils.js | 4 ++++ test/ShallowTraversal-spec.jsx | 10 ++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index 97f03d2fe..523ebe6b6 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -99,7 +99,7 @@ export function nodeHasProperty(node, propKey, stringifiedPropValue) { return false; } - if (propValue || propValue === 0 || propValue === '' || is(NaN, propValue)) { + if (propValue !== undefined) { return is(nodePropValue, propValue); } diff --git a/src/Utils.js b/src/Utils.js index ebf824a99..46d84834e 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -222,6 +222,10 @@ export function coercePropValue(propName, propValue) { return NaN; } + if (propValue === 'null') { + return null; + } + const trimmedValue = propValue.trim(); // if propValue includes quotes, it should be diff --git a/test/ShallowTraversal-spec.jsx b/test/ShallowTraversal-spec.jsx index 390756819..4f866634c 100644 --- a/test/ShallowTraversal-spec.jsx +++ b/test/ShallowTraversal-spec.jsx @@ -131,6 +131,16 @@ describe('ShallowTraversal', () => { expect(nodeHasProperty(
, 'foo', 'NaN')).to.equal(false); }); + it('should work with null', () => { + expect(nodeHasProperty(
, 'foo', 'null')).to.equal(true); + expect(nodeHasProperty(
, 'foo', 'null')).to.equal(false); + }); + + it('should work with false', () => { + expect(nodeHasProperty(
, 'foo', 'false')).to.equal(true); + expect(nodeHasProperty(
, 'foo', 'false')).to.equal(false); + }); + it('should throw when un unquoted string is passed in', () => { const node = (
); From eb2a229d228d99e9d487865f3898600ca8088de8 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Fri, 26 Aug 2016 17:36:55 -0700 Subject: [PATCH 16/57] [Tests] if no expected test is found, error out. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index af2e6cd81..f84e9247a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,7 @@ before_install: - 'if [ "${TRAVIS_NODE_VERSION}" != "0.6" ] && [ "${TRAVIS_NODE_VERSION}" != "0.9" ]; then npm install -g npm; fi' before_script: "sh install-relevant-react.sh" script: - - 'if [ -n "${EXAMPLE-}" ]; then npm run test:env -- "${EXAMPLE}" ; elif [ -n "${LINT-}" ]; then npm run lint; elif [ -n "${REACT-}" ]; then npm run travis; else echo "Test Skipped" ; fi' + - 'if [ -n "${EXAMPLE-}" ]; then npm run test:env -- "${EXAMPLE}" ; elif [ -n "${LINT-}" ]; then npm run lint; elif [ -n "${REACT-}" ]; then npm run travis; else false ; fi' after_script: - 'if [ "${TRAVIS_NODE_VERSION}" = "4" ] || [ "${TRAVIS_NODE_VERSION}" = "0.12" ]; then cat ./coverage/lcov.info | ./node_modules/.bin/coveralls ; fi' sudo: false From f83c529da9b5ad0292ce4b5d0e8ba3e383a23d3a Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Aug 2016 09:39:02 -0700 Subject: [PATCH 17/57] [Refactor] move `nodeHasProperty` implementation to `Utils` --- src/MountedTraversal.js | 4 +--- src/ShallowTraversal.js | 24 ++---------------------- src/Utils.js | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/MountedTraversal.js b/src/MountedTraversal.js index aa096f610..7465a1e70 100644 --- a/src/MountedTraversal.js +++ b/src/MountedTraversal.js @@ -11,10 +11,8 @@ import { AND, SELECTOR, nodeHasType, -} from './Utils'; -import { nodeHasProperty, -} from './ShallowTraversal'; +} from './Utils'; import { isDOMComponent, isCompositeComponent, diff --git a/src/ShallowTraversal.js b/src/ShallowTraversal.js index 523ebe6b6..9b32e209e 100644 --- a/src/ShallowTraversal.js +++ b/src/ShallowTraversal.js @@ -1,9 +1,7 @@ import React from 'react'; import isEmpty from 'lodash/isEmpty'; import isSubset from 'is-subset'; -import is from 'object-is'; import { - coercePropValue, propsOfNode, splitSelector, isCompoundSelector, @@ -11,6 +9,7 @@ import { AND, SELECTOR, nodeHasType, + nodeHasProperty, } from './Utils'; @@ -85,26 +84,7 @@ export function nodeHasId(node, id) { } -export function nodeHasProperty(node, propKey, stringifiedPropValue) { - const nodeProps = propsOfNode(node); - const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey); - if (descriptor && descriptor.get) { - return false; - } - const nodePropValue = nodeProps[propKey]; - - const propValue = coercePropValue(propKey, stringifiedPropValue); - - if (nodePropValue === undefined) { - return false; - } - - if (propValue !== undefined) { - return is(nodePropValue, propValue); - } - - return Object.prototype.hasOwnProperty.call(nodeProps, propKey); -} +export { nodeHasProperty }; export function nodeMatchesObjectProps(node, props) { return isSubset(propsOfNode(node), props); diff --git a/src/Utils.js b/src/Utils.js index 46d84834e..8b31148d1 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -252,6 +252,27 @@ export function coercePropValue(propName, propValue) { ); } +export function nodeHasProperty(node, propKey, stringifiedPropValue) { + const nodeProps = propsOfNode(node); + const descriptor = Object.getOwnPropertyDescriptor(nodeProps, propKey); + if (descriptor && descriptor.get) { + return false; + } + const nodePropValue = nodeProps[propKey]; + + const propValue = coercePropValue(propKey, stringifiedPropValue); + + if (nodePropValue === undefined) { + return false; + } + + if (propValue !== undefined) { + return is(nodePropValue, propValue); + } + + return Object.prototype.hasOwnProperty.call(nodeProps, propKey); +} + export function mapNativeEventNames(event) { const nativeToReactEventMap = { compositionend: 'compositionEnd', From 0314e2f812a4b11aabbce1327485256641c98291 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Aug 2016 09:45:22 -0700 Subject: [PATCH 18/57] =?UTF-8?q?[Tests]=20add=20tests=20to=20ensure=20?= =?UTF-8?q?=C2=B1Infinity=20works.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/ShallowTraversal-spec.jsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/ShallowTraversal-spec.jsx b/test/ShallowTraversal-spec.jsx index 4f866634c..dbadf0f89 100644 --- a/test/ShallowTraversal-spec.jsx +++ b/test/ShallowTraversal-spec.jsx @@ -141,6 +141,13 @@ describe('ShallowTraversal', () => { expect(nodeHasProperty(
, 'foo', 'false')).to.equal(false); }); + it('should work with ±Infinity', () => { + expect(nodeHasProperty(
, 'foo', 'Infinity')).to.equal(true); + expect(nodeHasProperty(
, 'foo', 'Infinity')).to.equal(false); + expect(nodeHasProperty(
, 'foo', '-Infinity')).to.equal(true); + expect(nodeHasProperty(
, 'foo', '-Infinity')).to.equal(false); + }); + it('should throw when un unquoted string is passed in', () => { const node = (
); From b02c5f6a23a364bb341b83cdc2d84a353cf8f094 Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Aug 2016 23:36:44 -0700 Subject: [PATCH 19/57] [Dev Deps] update `eslint`, `eslint-plugin-import`, `eslint-plugin-jsx-a11y`, `eslint-plugin-react`, `babel-register`, `babel-cli`, `babel-core` --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 27bea3973..32722e615 100644 --- a/package.json +++ b/package.json @@ -59,11 +59,11 @@ "object.values": "^1.0.3" }, "devDependencies": { - "babel-cli": "^6.11.4", - "babel-core": "^6.13.2", + "babel-cli": "^6.14.0", + "babel-core": "^6.14.0", "babel-eslint": "^6.1.2", "babel-preset-airbnb": "^2.0.0", - "babel-register": "^6.11.6", + "babel-register": "^6.14.0", "chai": "^3.5.0", "coveralls": "^2.11.12", "enzyme-example-jest": "^0.1.0", @@ -71,11 +71,11 @@ "enzyme-example-karma-webpack": "^0.1.4", "enzyme-example-mocha": "^0.1.0", "enzyme-example-react-native": "^0.1.0", - "eslint": "^3.3.1", + "eslint": "^3.4.0", "eslint-config-airbnb": "^10.0.1", - "eslint-plugin-import": "^1.13.0", - "eslint-plugin-jsx-a11y": "^2.1.0", - "eslint-plugin-react": "^6.1.2", + "eslint-plugin-import": "^1.14.0", + "eslint-plugin-jsx-a11y": "^2.2.0", + "eslint-plugin-react": "^6.2.0", "gitbook-cli": "^1.0.1", "istanbul": "^1.0.0-alpha.2", "jsdom": "^6.1.0", From 1d0fc67459955564d0455b56a9cc228aca01df2d Mon Sep 17 00:00:00 2001 From: Jordan Harband Date: Sun, 28 Aug 2016 23:38:13 -0700 Subject: [PATCH 20/57] [Deps] update `cheerio` --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 32722e615..d5cb6c9e5 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "author": "Leland Richardson ", "license": "MIT", "dependencies": { - "cheerio": "^0.20.0", + "cheerio": "^0.22.0", "is-subset": "^0.1.1", "lodash": "^4.15.0", "object-is": "^1.0.1", From acd1af643634813b276ce7f84096b1cc3645dcd1 Mon Sep 17 00:00:00 2001 From: Abhishek Pillai Date: Tue, 30 Aug 2016 16:31:18 -0400 Subject: [PATCH 21/57] Add Flatiron School to the organization list! --- INTHEWILD.md | 1 + 1 file changed, 1 insertion(+) diff --git a/INTHEWILD.md b/INTHEWILD.md index aa9a1f383..e24a84fab 100644 --- a/INTHEWILD.md +++ b/INTHEWILD.md @@ -12,6 +12,7 @@ Organizations - [Rangle.io](https://github.com/rangle) - [GoDaddy](https://github.com/godaddy) - [Airware](https://github.com/airware) + - [Flatiron School](https://github.com/flatiron-labs) Projects ---------- From c7097bd24ca4e9c26f26909973f90e32fbf82c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20Kub=C3=AD=C4=8Dek?= Date: Tue, 30 Aug 2016 23:34:04 +0200 Subject: [PATCH 22/57] Small typo fixed in docs --- docs/api/ShallowWrapper/parents.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/ShallowWrapper/parents.md b/docs/api/ShallowWrapper/parents.md index f5d23e620..ee24b195e 100644 --- a/docs/api/ShallowWrapper/parents.md +++ b/docs/api/ShallowWrapper/parents.md @@ -2,7 +2,7 @@ Returns a wrapper around all of the parents/ancestors of the wrapper. Does not include the node in the current wrapper. Optionally, a selector can be provided and it will filter the parents by -this selector +this selector. Note: can only be called on a wrapper of a single node. From f40dae8b975b6e2acf685af87b65a5fed3e89251 Mon Sep 17 00:00:00 2001 From: Jacob Walton Date: Thu, 1 Sep 2016 07:45:06 +0200 Subject: [PATCH 23/57] Remove redundant `exposedProperties` array (#571) --- docs/guides/jsdom.md | 3 --- withDom.js | 3 --- 2 files changed, 6 deletions(-) diff --git a/docs/guides/jsdom.md b/docs/guides/jsdom.md index a5b36fe18..5ffbd4f75 100644 --- a/docs/guides/jsdom.md +++ b/docs/guides/jsdom.md @@ -16,13 +16,10 @@ As a result, a standalone script like the one below is generally a good approach var jsdom = require('jsdom').jsdom; -var exposedProperties = ['window', 'navigator', 'document']; - global.document = jsdom(''); global.window = document.defaultView; Object.keys(document.defaultView).forEach((property) => { if (typeof global[property] === 'undefined') { - exposedProperties.push(property); global[property] = document.defaultView[property]; } }); diff --git a/withDom.js b/withDom.js index 19b49d36b..383b3e914 100644 --- a/withDom.js +++ b/withDom.js @@ -2,13 +2,10 @@ if (!global.document) { try { const jsdom = require('jsdom').jsdom; // could throw - const exposedProperties = ['window', 'navigator', 'document']; - global.document = jsdom(''); global.window = document.defaultView; Object.keys(document.defaultView).forEach((property) => { if (typeof global[property] === 'undefined') { - exposedProperties.push(property); global[property] = document.defaultView[property]; } }); From 50495740163455d127b9db51e18a971fa6f29aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Tue, 6 Sep 2016 20:37:26 +0200 Subject: [PATCH 24/57] Fixed issue with undefined being wrapped as nodes while constructing ReactWrapper (fixes #554) (#576) --- src/ReactWrapper.jsx | 4 +++- test/ReactWrapper-spec.jsx | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/ReactWrapper.jsx b/src/ReactWrapper.jsx index 131ba0aaa..6545ca14f 100644 --- a/src/ReactWrapper.jsx +++ b/src/ReactWrapper.jsx @@ -87,7 +87,9 @@ export default class ReactWrapper { } else { this.component = null; this.root = root; - if (!Array.isArray(nodes)) { + if (!nodes) { + this.nodes = []; + } else if (!Array.isArray(nodes)) { this.node = nodes; this.nodes = [nodes]; } else { diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 503eee358..36d3911be 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -3005,5 +3005,18 @@ describeWithDOM('mount', () => { expect(wrapper.name()).to.equal('div'); }); }); + + describe('.ref()', () => { + it('unavailable ref should return empty nodes', () => { + class WithoutRef extends React.Component { + render() { return
; } + } + const wrapper = mount(); + const ref = wrapper.ref('not-a-ref'); + + expect(ref.length).to.equal(0); + expect(ref.isEmpty()).to.equal(true); + }); + }); }); }); From 4663aaa61ee59fba9ce76cccb2d0bdf528374317 Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Sun, 11 Sep 2016 21:47:35 -0500 Subject: [PATCH 25/57] Warn if selector contains a psuedo-class --- src/Utils.js | 30 +++++++++++++++++++---- test/ReactWrapper-spec.jsx | 4 +-- test/Utils-spec.jsx | 50 ++++++++++++++++++++------------------ 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/src/Utils.js b/src/Utils.js index 8b31148d1..c011c9ad7 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -165,14 +165,31 @@ export function splitSelector(selector) { return selector.split(/(?=\.|\[.*\])|(?=#|\[#.*\])/); } -export function isSimpleSelector(selector) { - // any of these characters pretty much guarantee it's a complex selector - return !/[~\s:>]/.test(selector); + +const containsQuotes = /'|"/; +const containsColon = /:/; + + +export function isPsuedoClassSelector(selector) { + if (containsColon.test(selector)) { + if (!containsQuotes.test(selector)) { + return true; + } + const tokens = selector.split(containsQuotes); + for (let i = 0; i < tokens.length; i++) { + const token = tokens[i]; + if (containsColon.test(token) && i % 2 === 0) { + return true; + } + } + return false; + } + return false; } -export function selectorError(selector) { +export function selectorError(selector, type = '') { return new TypeError( - `Enzyme received a complex CSS selector ('${selector}') that it does not currently support` + `Enzyme received a ${type} CSS selector ('${selector}') that it does not currently support` ); } @@ -187,6 +204,9 @@ export const SELECTOR = { }; export function selectorType(selector) { + if (isPsuedoClassSelector(selector)) { + throw selectorError(selector, 'psudo-class'); + } if (selector[0] === '.') { return SELECTOR.CLASS_TYPE; } else if (selector[0] === '#') { diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 36d3911be..2adb8465e 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -390,12 +390,12 @@ describeWithDOM('mount', () => { React.createElement('div', null, React.createElement('span', { '123-foo': 'bar', '-foo': 'bar', - ':foo': 'bar', + '+foo': 'bar', })) ); expect(wrapper.find('[-foo]')).to.have.length(0, '-foo'); - expect(wrapper.find('[:foo]')).to.have.length(0, ':foo'); + expect(wrapper.find('[+foo]')).to.have.length(0, '+foo'); expect(wrapper.find('[123-foo]')).to.have.length(0, '123-foo'); }); diff --git a/test/Utils-spec.jsx b/test/Utils-spec.jsx index 358eed824..ca6215a05 100644 --- a/test/Utils-spec.jsx +++ b/test/Utils-spec.jsx @@ -9,7 +9,7 @@ import { coercePropValue, getNode, nodeEqual, - isSimpleSelector, + isPsuedoClassSelector, propFromEvent, SELECTOR, selectorType, @@ -246,39 +246,43 @@ describe('Utils', () => { }); - describe('isSimpleSelector', () => { + describe('isPsuedoClassSelector', () => { + describe('prohibited selectors', () => { - function isComplex(selector) { + function isNotPsuedo(selector) { it(selector, () => { - expect(isSimpleSelector(selector)).to.equal(false); + expect(isPsuedoClassSelector(selector)).to.equal(false); }); } - - isComplex('.foo .bar'); - isComplex(':visible'); - isComplex('.foo>.bar'); - isComplex('.foo > .bar'); - isComplex('.foo~.bar'); - + isNotPsuedo('.foo'); + isNotPsuedo('div'); + isNotPsuedo('.foo .bar'); + isNotPsuedo('[hover]'); + isNotPsuedo('[checked=""]'); + isNotPsuedo('[checked=":checked"]'); + isNotPsuedo('[checked=\':checked\']'); + isNotPsuedo('.foo>.bar'); + isNotPsuedo('.foo > .bar'); + isNotPsuedo('.foo~.bar'); + isNotPsuedo('#foo'); }); describe('allowed selectors', () => { - function isSimple(selector) { + function isPsuedo(selector) { it(selector, () => { - expect(isSimpleSelector(selector)).to.equal(true); + expect(isPsuedoClassSelector(selector)).to.equal(true); }); } - - isSimple('.foo'); - isSimple('.foo-and-foo'); - isSimple('input[foo="bar"]'); - isSimple('input[foo="bar"][bar="baz"][baz="foo"]'); - isSimple('.FoOaNdFoO'); - isSimple('tag'); - isSimple('.foo.bar'); - isSimple('input.foo'); - + isPsuedo(':checked'); + isPsuedo(':focus'); + isPsuedo(':hover'); + isPsuedo(':disabled'); + isPsuedo(':any'); + isPsuedo(':last-child'); + isPsuedo(':nth-child(1)'); + isPsuedo('div:checked'); + isPsuedo('[data-foo=":hover"]:hover'); }); }); From 2d94e5388ec295d8bb28bb3976ffc2890061cbfd Mon Sep 17 00:00:00 2001 From: Brandon Dail Date: Sun, 11 Sep 2016 23:54:41 -0500 Subject: [PATCH 26/57] use .some() instead of for loop Also pseudo-spelling errors --- src/Utils.js | 16 ++++++-------- test/Utils-spec.jsx | 52 ++++++++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/src/Utils.js b/src/Utils.js index c011c9ad7..15bc375bb 100644 --- a/src/Utils.js +++ b/src/Utils.js @@ -170,19 +170,15 @@ const containsQuotes = /'|"/; const containsColon = /:/; -export function isPsuedoClassSelector(selector) { +export function isPseudoClassSelector(selector) { if (containsColon.test(selector)) { if (!containsQuotes.test(selector)) { return true; } const tokens = selector.split(containsQuotes); - for (let i = 0; i < tokens.length; i++) { - const token = tokens[i]; - if (containsColon.test(token) && i % 2 === 0) { - return true; - } - } - return false; + return tokens.some((token, i) => + containsColon.test(token) && i % 2 === 0 + ); } return false; } @@ -204,8 +200,8 @@ export const SELECTOR = { }; export function selectorType(selector) { - if (isPsuedoClassSelector(selector)) { - throw selectorError(selector, 'psudo-class'); + if (isPseudoClassSelector(selector)) { + throw selectorError(selector, 'pseudo-class'); } if (selector[0] === '.') { return SELECTOR.CLASS_TYPE; diff --git a/test/Utils-spec.jsx b/test/Utils-spec.jsx index ca6215a05..808ad355b 100644 --- a/test/Utils-spec.jsx +++ b/test/Utils-spec.jsx @@ -9,7 +9,7 @@ import { coercePropValue, getNode, nodeEqual, - isPsuedoClassSelector, + isPseudoClassSelector, propFromEvent, SELECTOR, selectorType, @@ -246,43 +246,43 @@ describe('Utils', () => { }); - describe('isPsuedoClassSelector', () => { + describe('isPseudoClassSelector', () => { describe('prohibited selectors', () => { - function isNotPsuedo(selector) { + function isNotPseudo(selector) { it(selector, () => { - expect(isPsuedoClassSelector(selector)).to.equal(false); + expect(isPseudoClassSelector(selector)).to.equal(false); }); } - isNotPsuedo('.foo'); - isNotPsuedo('div'); - isNotPsuedo('.foo .bar'); - isNotPsuedo('[hover]'); - isNotPsuedo('[checked=""]'); - isNotPsuedo('[checked=":checked"]'); - isNotPsuedo('[checked=\':checked\']'); - isNotPsuedo('.foo>.bar'); - isNotPsuedo('.foo > .bar'); - isNotPsuedo('.foo~.bar'); - isNotPsuedo('#foo'); + isNotPseudo('.foo'); + isNotPseudo('div'); + isNotPseudo('.foo .bar'); + isNotPseudo('[hover]'); + isNotPseudo('[checked=""]'); + isNotPseudo('[checked=":checked"]'); + isNotPseudo('[checked=\':checked\']'); + isNotPseudo('.foo>.bar'); + isNotPseudo('.foo > .bar'); + isNotPseudo('.foo~.bar'); + isNotPseudo('#foo'); }); describe('allowed selectors', () => { - function isPsuedo(selector) { + function isPseudo(selector) { it(selector, () => { - expect(isPsuedoClassSelector(selector)).to.equal(true); + expect(isPseudoClassSelector(selector)).to.equal(true); }); } - isPsuedo(':checked'); - isPsuedo(':focus'); - isPsuedo(':hover'); - isPsuedo(':disabled'); - isPsuedo(':any'); - isPsuedo(':last-child'); - isPsuedo(':nth-child(1)'); - isPsuedo('div:checked'); - isPsuedo('[data-foo=":hover"]:hover'); + isPseudo(':checked'); + isPseudo(':focus'); + isPseudo(':hover'); + isPseudo(':disabled'); + isPseudo(':any'); + isPseudo(':last-child'); + isPseudo(':nth-child(1)'); + isPseudo('div:checked'); + isPseudo('[data-foo=":hover"]:hover'); }); }); From 7906cbb205114dd0e7f9df91d63f9e1601b76318 Mon Sep 17 00:00:00 2001 From: Gregory Terzian Date: Mon, 12 Sep 2016 17:17:48 +0800 Subject: [PATCH 27/57] Linking to the actual Selector page --- docs/GLOSSARY.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md index e7fc582dd..844287a88 100644 --- a/docs/GLOSSARY.md +++ b/docs/GLOSSARY.md @@ -2,7 +2,7 @@ A Selector in enzyme is similar to a CSS selector, but can be a number of other things as well in order to easily specify a criteria by which you want to find nodes in a enzyme wrapper. See the -Selector page for more information. +[Selector page](/docs/api/selector.md) for more information. # wrapper From 12348803f81f39ddb6e90916b56a20ae234e2fd4 Mon Sep 17 00:00:00 2001 From: Kevin Huang Date: Mon, 5 Sep 2016 11:37:22 -0700 Subject: [PATCH 28/57] Add documentation note clarifying shallow prop functions --- docs/api/ShallowWrapper/prop.md | 32 +++++++++++++++++++++++++++----- docs/api/ShallowWrapper/props.md | 29 +++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/docs/api/ShallowWrapper/prop.md b/docs/api/ShallowWrapper/prop.md index d19f6fe85..6095c4132 100644 --- a/docs/api/ShallowWrapper/prop.md +++ b/docs/api/ShallowWrapper/prop.md @@ -1,13 +1,16 @@ # `.prop(key) => Any` -Returns the prop value for the node of the current wrapper with the provided key. +Returns the prop value for the root node of the wrapper with the provided key. +`.prop(key)` can only be called on a wrapper of a single node. -NOTE: can only be called on a wrapper of a single node. +NOTE: When called on a shallow wrapper, `.prop(key)` will only return values for props that exist for the parent element of the component, not the whole React component. To return the props for the +entire React component, use `wrapper.instance().props`. See [`.instance() => +ReactComponent`](instance.md) #### Arguments 1. `key` (`String`): The prop name such that this will return value will be the `this.props[key]` -of the component instance. +of the parent element of the component. @@ -15,8 +18,27 @@ of the component instance. ```jsx -const wrapper = shallow(); -expect(wrapper.prop('foo')).to.equal(10); +const MyComponent = React.createClass({ + render() { + return ( +
Hello
+ ) + } +}) +const wrapper = shallow(); +expect(wrapper.prop('includedProp')).to.equal("Success!"); + +// Warning: .prop(key) only returns values for props that exist in the parent element. +// See the note above about wrapper.instance().props to return all props in the React component. + +wrapper.prop('includedProp'); +// "Success!" + +wrapper.prop('excludedProp'); +// undefined + +wrapper.instance().props.excludedProp; +// "I'm not included" ``` diff --git a/docs/api/ShallowWrapper/props.md b/docs/api/ShallowWrapper/props.md index 6d480d8a0..271e4b5fd 100644 --- a/docs/api/ShallowWrapper/props.md +++ b/docs/api/ShallowWrapper/props.md @@ -1,16 +1,37 @@ # `.props() => Object` -Returns the props hash for the current node of the wrapper. +Returns the props hash for the root node of the wrapper. `.props()` can only be called on a wrapper of a single node. -NOTE: can only be called on a wrapper of a single node. +NOTE: When called on a shallow wrapper, `.props()` will only return the +props for the parent element in the component, not the whole React component. To return the props for the +entire React component, use `wrapper.instance().props`. See [`.instance() => +ReactComponent`](instance.md) #### Example ```jsx -const wrapper = shallow(); -expect(wrapper.props().foo).to.equal(10); +const MyComponent = React.createClass({ + render() { + return ( +
Hello
+ ) + } +}) +const wrapper = shallow(); +expect(wrapper.props().includedProp).to.equal("Success!"); + +// Warning: .props() only returns props that are passed to the parent element, +// which does not include excludedProp in this example. +// See the note above about wrapper.instance().props. + +wrapper.props(); +// {children: "Hello", className: "foo bar", includedProp="Success!"} + +wrapper.instance().props; +// {children: "Hello", className: "foo bar", includedProp:"Success!", excludedProp: "I'm not included"} + ``` From d9f26416b7a000afff3b83f7097f6351e6691cb6 Mon Sep 17 00:00:00 2001 From: Kevin Huang Date: Tue, 6 Sep 2016 00:35:54 -0700 Subject: [PATCH 29/57] Improve props & prop documentation by using correct root node term --- docs/api/ShallowWrapper/prop.md | 11 ++++++----- docs/api/ShallowWrapper/props.md | 13 +++++++------ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/api/ShallowWrapper/prop.md b/docs/api/ShallowWrapper/prop.md index 6095c4132..9ab4c6c87 100644 --- a/docs/api/ShallowWrapper/prop.md +++ b/docs/api/ShallowWrapper/prop.md @@ -3,14 +3,15 @@ Returns the prop value for the root node of the wrapper with the provided key. `.prop(key)` can only be called on a wrapper of a single node. -NOTE: When called on a shallow wrapper, `.prop(key)` will only return values for props that exist for the parent element of the component, not the whole React component. To return the props for the -entire React component, use `wrapper.instance().props`. See [`.instance() => -ReactComponent`](instance.md) +NOTE: When called on a shallow wrapper, `.prop(key)` will return values for +props on the root node that the component *renders*, not the component itself. +To return the props for the entire React component, use `wrapper.instance().props`. +See [`.instance() => ReactComponent`](instance.md) #### Arguments 1. `key` (`String`): The prop name such that this will return value will be the `this.props[key]` -of the parent element of the component. +of the root node of the component. @@ -28,7 +29,7 @@ const MyComponent = React.createClass({ const wrapper = shallow(); expect(wrapper.prop('includedProp')).to.equal("Success!"); -// Warning: .prop(key) only returns values for props that exist in the parent element. +// Warning: .prop(key) only returns values for props that exist in the root node. // See the note above about wrapper.instance().props to return all props in the React component. wrapper.prop('includedProp'); diff --git a/docs/api/ShallowWrapper/props.md b/docs/api/ShallowWrapper/props.md index 271e4b5fd..6fa070932 100644 --- a/docs/api/ShallowWrapper/props.md +++ b/docs/api/ShallowWrapper/props.md @@ -1,11 +1,12 @@ # `.props() => Object` -Returns the props hash for the root node of the wrapper. `.props()` can only be called on a wrapper of a single node. +Returns the props hash for the root node of the wrapper. `.props()` can only be +called on a wrapper of a single node. -NOTE: When called on a shallow wrapper, `.props()` will only return the -props for the parent element in the component, not the whole React component. To return the props for the -entire React component, use `wrapper.instance().props`. See [`.instance() => -ReactComponent`](instance.md) +NOTE: When called on a shallow wrapper, `.props()` will return values for +props on the root node that the component *renders*, not the component itself. +To return the props for the entire React component, use `wrapper.instance().props`. +See [`.instance() => ReactComponent`](instance.md) #### Example @@ -22,7 +23,7 @@ const MyComponent = React.createClass({ const wrapper = shallow(); expect(wrapper.props().includedProp).to.equal("Success!"); -// Warning: .props() only returns props that are passed to the parent element, +// Warning: .props() only returns props that are passed to the root node, // which does not include excludedProp in this example. // See the note above about wrapper.instance().props. From cf467a0ef9644dfe8767db75de47b4edffe8dcbb Mon Sep 17 00:00:00 2001 From: AugustinLF Date: Sun, 3 Jul 2016 19:47:11 +0200 Subject: [PATCH 30/57] Remove arbitrary props from DOM elements closes #480 --- test/ReactWrapper-spec.jsx | 53 ++++++++++++++++++++++-------------- test/ShallowWrapper-spec.jsx | 14 ++++++++-- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/test/ReactWrapper-spec.jsx b/test/ReactWrapper-spec.jsx index 2adb8465e..689b6c3b4 100644 --- a/test/ReactWrapper-spec.jsx +++ b/test/ReactWrapper-spec.jsx @@ -384,7 +384,7 @@ describeWithDOM('mount', () => { }); - it('should not find components with invalid attributes', () => { + it.skip('should not find components with invalid attributes', () => { // Invalid attributes aren't valid JSX, so manual instantiation is necessary const wrapper = mount( React.createElement('div', null, React.createElement('span', { @@ -514,16 +514,21 @@ describeWithDOM('mount', () => { expect(wrapper.find('button').length).to.equal(1); }); - it('should support object property selectors', () => { + it.skip('should support object property selectors', () => { + class Foo extends React.Component { + render() { + return ; + } + } const wrapper = mount(
-