Skip to content

Commit 7a8db3d

Browse files
authored
Filter Cloudinary custom props from rendered div (#37)
* Filter Cloudinary custom props from rendered div When rendering the div underlying CloudinaryContext remove Cloudinary custom props to avoid errors such as "React does not recognize the `cloudName` prop on a DOM element" * Restore single quote import style, add case to unit test * Fix test after merge with React 16
1 parent 2c5eeec commit 7a8db3d

File tree

3 files changed

+55
-17
lines changed

3 files changed

+55
-17
lines changed

src/components/CloudinaryContext/CloudinaryContext.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,26 @@ class CloudinaryContext extends CloudinaryComponent {
3030
}
3131

3232
render() {
33-
return (
34-
<div {...this.props}>{this.props.children}</div>
35-
);
33+
// Remove Cloudinary custom props that don't belong to div
34+
const nonCloudinaryProps = Object.keys(this.props)
35+
.filter(propName => !CloudinaryContext.CLOUDINARY_PROPS[propName])
36+
.reduce((allowedProps, currentProp) => {
37+
allowedProps[currentProp] = this.props[currentProp];
38+
return allowedProps;
39+
}, {});
40+
return <div {...nonCloudinaryProps}>{this.props.children}</div>;
3641
}
3742
}
3843

44+
// Map Cloudinary props from array to object for efficient lookup
45+
CloudinaryContext.CLOUDINARY_PROPS = CloudinaryComponent.VALID_OPTIONS.reduce(
46+
(accumulator, cloudinaryPropName) => {
47+
accumulator[cloudinaryPropName] = true;
48+
return accumulator;
49+
},
50+
{}
51+
);
52+
3953
CloudinaryContext.propTypes = CloudinaryComponent.propTypes;
4054
CloudinaryContext.defaultProps = {};
4155
CloudinaryContext.childContextTypes = CloudinaryComponent.contextTypes;

test/ContextTest.js

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import React from 'react';
22
import { expect } from 'chai';
3-
import { shallow, mount, render } from 'enzyme';
3+
import { mount } from 'enzyme';
44
import Image from '../src/components/Image';
55
import Transformation from '../src/components/Transformation';
66
import CloudinaryContext from '../src/components/CloudinaryContext';
77

8-
98
describe('CloudinaryContext', () => {
10-
beforeEach(() => {
11-
});
129
it("should pass properties to children", function() {
1310
let tag = mount(
1411
<CloudinaryContext className="root" cloudName="demo">
15-
<Image publicId="sample" />
12+
<Image publicId="sample" />
1613
</CloudinaryContext>
1714
);
1815

@@ -23,16 +20,43 @@ describe('CloudinaryContext', () => {
2320
expect(img.instance().state.url).to.equal("http://res.cloudinary.com/demo/image/upload/sample");
2421
});
2522

23+
it("should remove Cloudinary custom properties from CloudinaryContext component", function() {
24+
let html = mount(
25+
<CloudinaryContext
26+
className="root"
27+
cloudName="demo"
28+
quality="auto"
29+
secure="true"
30+
role="tab"
31+
aria-live="polite"
32+
>
33+
<Image publicId="sample" />
34+
</CloudinaryContext>
35+
);
36+
37+
const contextDiv = html.find("div");
38+
expect(contextDiv.find(".root").length).to.equal(1);
39+
expect(contextDiv.find("[role='tab']").length).to.equal(1);
40+
expect(contextDiv.find("[aria-live='polite']").length).to.equal(1);
41+
expect(contextDiv.find("[cloudName='demo']").length).to.equal(0);
42+
expect(contextDiv.find("[quality]").length).to.equal(0);
43+
44+
// Verify that transformations from context are applied to components
45+
expect(contextDiv.find('img').prop("src")).to.equal("https://res.cloudinary.com/demo/image/upload/q_auto/sample");
46+
});
47+
2648
it("should allow chained Contexts", function() {
2749
let tag = mount(
2850
<CloudinaryContext cloudName="demo">
2951
<CloudinaryContext width="100" crop="scale">
30-
<Image publicId="sample"/>
52+
<Image publicId="sample" />
3153
</CloudinaryContext>
3254
</CloudinaryContext>
3355
);
34-
expect(tag.containsMatchingElement(
35-
<img src="http://res.cloudinary.com/demo/image/upload/c_scale,w_100/sample"/>
36-
)).to.equal(true);
56+
expect(
57+
tag.containsMatchingElement(
58+
<img src="http://res.cloudinary.com/demo/image/upload/c_scale,w_100/sample" />
59+
)
60+
).to.equal(true);
3761
});
38-
});
62+
});

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,6 +1809,10 @@ center-align@^0.1.1:
18091809
align-text "^0.1.3"
18101810
lazy-cache "^1.0.3"
18111811

1812+
chai-string@^1.4.0:
1813+
version "1.4.0"
1814+
resolved "https://registry.yarnpkg.com/chai-string/-/chai-string-1.4.0.tgz#359140c051d36a4e4b1a5fc6b910152f438a8d49"
1815+
18121816
chai@^4.1.2:
18131817
version "4.1.2"
18141818
resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c"
@@ -4969,10 +4973,6 @@ react-addons-create-fragment@^15.5.3:
49694973
loose-envify "^1.3.1"
49704974
object-assign "^4.1.0"
49714975

4972-
react-addons-test-utils@^15.6.2:
4973-
version "15.6.2"
4974-
resolved "https://registry.yarnpkg.com/react-addons-test-utils/-/react-addons-test-utils-15.6.2.tgz#c12b6efdc2247c10da7b8770d185080a7b047156"
4975-
49764976
react-docgen@^2.15.0:
49774977
version "2.20.0"
49784978
resolved "https://registry.yarnpkg.com/react-docgen/-/react-docgen-2.20.0.tgz#41a6da483a34a4aaed041a9909f5e61864d681cb"

0 commit comments

Comments
 (0)