Skip to content

Commit b565405

Browse files
committed
fix: serialize script elements wrapped in components
1 parent f98247e commit b565405

File tree

6 files changed

+176
-15
lines changed

6 files changed

+176
-15
lines changed

package-lock.json

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"@types/jest": "^24.0.17",
5252
"@types/node": "^12.7.2",
5353
"@types/react": "^16.8.25",
54+
"@types/react-test-renderer": "^16.9.1",
5455
"@typescript-eslint/eslint-plugin": "^2.0.0",
5556
"@typescript-eslint/parser": "^2.0.0",
5657
"eslint": "^6.1.0",
@@ -63,6 +64,7 @@
6364
"jest-runner-prettier": "^0.3.1",
6465
"prettier": "^1.18.2",
6566
"react": "^16.9.0",
67+
"react-test-renderer": "^16.12.0",
6668
"semantic-release": "^15.13.21",
6769
"ts-jest": "^24.0.2",
6870
"typescript": "^3.5.3"

src/__snapshots__/index.test.tsx.snap

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,60 @@ exports[`Serialization function serializes a JSON+LD script element with data se
88
</script>
99
`;
1010

11+
exports[`Serialization function serializes a script element created using React.createElement 1`] = `
12+
<script
13+
type="application/ld+json"
14+
>
15+
Object {
16+
"@context": "http://schema.org",
17+
"@id": "https://example.dev/example_thing",
18+
"@type": "Thing",
19+
}
20+
</script>
21+
`;
22+
23+
exports[`Serialization function serializes a script element with data correctly 1`] = `
24+
<script
25+
type="application/ld+json"
26+
>
27+
Object {
28+
"@context": "http://schema.org",
29+
"@id": "https://example.dev/example_thing",
30+
"@type": "Thing",
31+
}
32+
</script>
33+
`;
34+
35+
exports[`Serialization function serializes a script element wrapped in a component 1`] = `
36+
<div>
37+
<div>
38+
<script
39+
type="application/ld+json"
40+
>
41+
Object {
42+
"@context": "http://schema.org",
43+
"@id": "https://example.dev/example_thing",
44+
"@type": "Thing",
45+
}
46+
</script>
47+
</div>
48+
</div>
49+
`;
50+
51+
exports[`Serialization function serializes a wrapped script element with data correctly 1`] = `
52+
<div>
53+
<script
54+
type="application/ld+json"
55+
>
56+
Object {
57+
"@context": "http://schema.org",
58+
"@id": "https://example.dev/example_thing",
59+
"@type": "Thing",
60+
}
61+
</script>
62+
</div>
63+
`;
64+
1165
exports[`Serialization module matches expectations 1`] = `
1266
Object {
1367
"print": [Function],

src/index.test.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as React from "react";
2+
import renderer from "react-test-renderer";
23
import serializer from ".";
34

45
describe("Serializer test function", () => {
@@ -65,6 +66,87 @@ describe("Serialization function", () => {
6566

6667
expect(ldScriptElement).toMatchSnapshot();
6768
});
69+
70+
it("serializes a script element with data correctly", () => {
71+
expect.addSnapshotSerializer(serializer);
72+
73+
const element = (
74+
<script
75+
type="application/ld+json"
76+
dangerouslySetInnerHTML={{
77+
__html: JSON.stringify({
78+
"@context": "http://schema.org",
79+
"@type": "Thing",
80+
"@id": "https://example.dev/example_thing"
81+
})
82+
}}
83+
/>
84+
);
85+
86+
expect(element).toMatchSnapshot();
87+
});
88+
89+
it("serializes a wrapped script element with data correctly", () => {
90+
expect.addSnapshotSerializer(serializer);
91+
92+
const element = (
93+
<div>
94+
<script
95+
type="application/ld+json"
96+
dangerouslySetInnerHTML={{
97+
__html: JSON.stringify({
98+
"@context": "http://schema.org",
99+
"@type": "Thing",
100+
"@id": "https://example.dev/example_thing"
101+
})
102+
}}
103+
/>
104+
</div>
105+
);
106+
107+
expect(element).toMatchSnapshot();
108+
});
109+
110+
it("serializes a script element created using React.createElement", () => {
111+
expect.addSnapshotSerializer(serializer);
112+
113+
const element = React.createElement("script", {
114+
type: "application/ld+json",
115+
dangerouslySetInnerHTML: {
116+
__html: JSON.stringify({
117+
"@context": "http://schema.org",
118+
"@type": "Thing",
119+
"@id": "https://example.dev/example_thing"
120+
})
121+
}
122+
});
123+
124+
expect(element).toMatchSnapshot();
125+
});
126+
127+
it("serializes a script element wrapped in a component", () => {
128+
expect.addSnapshotSerializer(serializer);
129+
130+
const Component = () => (
131+
<div>
132+
<div>
133+
<script
134+
type="application/ld+json"
135+
dangerouslySetInnerHTML={{
136+
__html: JSON.stringify({
137+
"@context": "http://schema.org",
138+
"@type": "Thing",
139+
"@id": "https://example.dev/example_thing"
140+
})
141+
}}
142+
/>
143+
</div>
144+
</div>
145+
);
146+
147+
const tree = renderer.create(<Component />).toJSON();
148+
expect(tree).toMatchSnapshot();
149+
});
68150
});
69151

70152
describe("Serialization module", () => {

src/index.tsx

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,14 @@
1-
/* eslint-disable @typescript-eslint/no-explicit-any */
2-
31
import * as React from "react";
42

5-
function hasValidProps(val: any): boolean {
6-
return Boolean(
7-
val.props.dangerouslySetInnerHTML &&
8-
val.props.type &&
9-
val.props.type === "application/ld+json"
10-
);
11-
}
12-
133
const JSONLDSerializer: jest.SnapshotSerializerPlugin = {
144
test(val) {
155
return Boolean(
166
val &&
17-
React.isValidElement(val) &&
7+
// React.isValidElement(val) && // Previously we were using this API to shortcut testing if an object was a React object, but this produces false negatives on <script/> elements wrapped in Components. While it might take longer to fail on some tests, it should produce a negligable effect.
188
val.type === "script" &&
19-
hasValidProps(val)
9+
val.props.dangerouslySetInnerHTML &&
10+
val.props.type &&
11+
val.props.type === "application/ld+json"
2012
);
2113
},
2214

tsconfig.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
// "allowJs": true, /* Allow javascript files to be compiled. */
99
// "checkJs": true, /* Report errors in .js files. */
1010
"jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */,
11-
// "declaration": true, /* Generates corresponding '.d.ts' file. */
12-
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
13-
// "sourceMap": true, /* Generates corresponding '.map' file. */
11+
"declaration": true /* Generates corresponding '.d.ts' file. */,
12+
"declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
13+
"sourceMap": true /* Generates corresponding '.map' file. */,
1414
// "outFile": "./", /* Concatenate and emit output to single file. */
1515
"outDir": "./dist" /* Redirect output structure to the directory. */,
1616
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */

0 commit comments

Comments
 (0)