Skip to content
This repository was archived by the owner on Jun 22, 2022. It is now read-only.

Commit 1fb6cf1

Browse files
committed
Improve mocking if source does not contain any jsx expression
1 parent 718f56f commit 1fb6cf1

File tree

4 files changed

+306
-46
lines changed

4 files changed

+306
-46
lines changed

README.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
## Easy automock your react components
1+
## Easy automock your external react components
22

3-
Do you like write component tests? Do you like react-test-renderer more than shallow renderer? Do you feel sometimes that it would be great to combine both shallow renderer and react-test-renderer to prevent rendering inner components? Do you feel headcache when writing tests for something like [styled-components](https://www.styled-components.com/) ?
3+
Do you like write component tests? Do you like react-test-renderer more than shallow renderer? Do you feel sometimes that it would be great to combine both shallow renderer and react-test-renderer to prevent rendering inner components? Do you feel headcache when writing tests for something like [styled-components](https://www.styled-components.com/) ? Are you bored to write numerous ```jest.mock()``` calls to mock your component?
44

5-
If answer for these all questions is "Yes" then you come to the right place.
5+
If the answer for any of these questions is "Yes" then you come to the right place.
66

77

88
Much often, you want to mock/don't render external components. Almost always these external components are being imported through import statement ```import A from "./a"```. And very often you want to full render the inner (helpers or styled) components:
@@ -90,15 +90,22 @@ Ideally, you want this snapshot:
9090

9191
```
9292

93-
This is achievable by mocking components using ```jest.mock()``` but this is boring and repetetive task, especially when you have to mock many components.
93+
This is achievable by mocking components using ```jest.mock()``` but this is boring and repetetive task, especially when you have to mock many components:
94+
95+
```jsx
96+
jest.mock("../AnotherComp", () => "AnotherComp");
97+
jest.mock("../Button", () => "Button");
98+
jest.mock("../SomeComp", () => ({ SomeComp: "SomeComp" })); // very ugly for named exports
99+
// etc...
100+
```
94101

95102
Finally, now you can just use ```jest-mock-external-components```:
96103

97-
```js
104+
```jsx
98105
import Component from "../mycomponent";
99106
import { mockExternalComponents } from "jest-mock-external-components";
100107
mockExteralComponents(Component);
101-
// will mock <Button /> and <AnotherComp />
108+
// will automatically mock <Button /> and <AnotherComp />
102109

103110
// Use react-test-renderer
104111
const t = create(<Component />);
@@ -122,4 +129,4 @@ Add to your ```.babelrc``` / ```.babelrc.js``` / ```babel.config.js```
122129
```
123130

124131
## Caveats
125-
After mocking, at beginning of the test file the ```jest.resetModules()``` will be called. Make sure you won't set internal state somewhere before (for example in setupFiles/setupTestFrameworkFile)
132+
After mocking, at beginning of the test file the ```jest.resetModules()``` will be called. Make sure you are not setting internal state somewhere before (for example in setupFiles/setupTestFrameworkFile)

src/__tests__/__snapshots__/babel.spec.ts.snap

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,188 @@ const Mocks = [{
10231023
exports.Mocks = Mocks;"
10241024
`;
10251025

1026+
exports[`For component like source Works for alwaysMockIdentifiers without JSX opening element 1`] = `
1027+
"import A from \\"a\\";
1028+
import { B } from \\"../b\\";
1029+
import C from \\"c\\";
1030+
import D from \\"d\\";
1031+
import styled from \\"styled\\";
1032+
const StyledA = styled(A)\`\`;
1033+
const StyledB = styled(A.B);
1034+
const StyledC = styled(A.C, {});
1035+
const StyledD = styled(A.D, {})\`font-size: 8em;\`;
1036+
const B1 = A.withComponent(C.C1);
1037+
const B2 = styled(D)\`\`;
1038+
const B3 = nonStyled(C.C2);
1039+
export const Mocks = [{
1040+
identifier: \\"A\\",
1041+
path: \\"a\\",
1042+
type: \\"default\\"
1043+
}, {
1044+
identifier: \\"A.B\\",
1045+
path: \\"a\\",
1046+
type: \\"default\\"
1047+
}, {
1048+
identifier: \\"A.C\\",
1049+
path: \\"a\\",
1050+
type: \\"default\\"
1051+
}, {
1052+
identifier: \\"A.D\\",
1053+
path: \\"a\\",
1054+
type: \\"default\\"
1055+
}, {
1056+
identifier: \\"C.C1\\",
1057+
path: \\"c\\",
1058+
type: \\"default\\"
1059+
}, {
1060+
identifier: \\"D\\",
1061+
path: \\"d\\",
1062+
type: \\"default\\"
1063+
}];"
1064+
`;
1065+
1066+
exports[`For component like source Works for alwaysMockIdentifiers without JSX opening element 2`] = `
1067+
"\\"use strict\\";
1068+
1069+
Object.defineProperty(exports, \\"__esModule\\", {
1070+
value: true
1071+
});
1072+
exports.Mocks = void 0;
1073+
1074+
var _a = _interopRequireDefault(require(\\"a\\"));
1075+
1076+
var _b = require(\\"../b\\");
1077+
1078+
var _c = _interopRequireDefault(require(\\"c\\"));
1079+
1080+
var _d = _interopRequireDefault(require(\\"d\\"));
1081+
1082+
var _styled = _interopRequireDefault(require(\\"styled\\"));
1083+
1084+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1085+
1086+
const StyledA =
1087+
/*#__PURE__*/
1088+
(0, _styled.default)(_a.default, {
1089+
target: \\"e1h80wsp0\\"
1090+
})();
1091+
const StyledB = (0, _styled.default)(_a.default.B);
1092+
const StyledC = (0, _styled.default)(_a.default.C, {});
1093+
const StyledD =
1094+
/*#__PURE__*/
1095+
(0, _styled.default)(_a.default.D, {
1096+
target: \\"e1h80wsp1\\"
1097+
})(\\"font-size:8em;\\");
1098+
1099+
const B1 = _a.default.withComponent(_c.default.C1, {
1100+
target: \\"e1h80wsp2\\"
1101+
});
1102+
1103+
const B2 =
1104+
/*#__PURE__*/
1105+
(0, _styled.default)(_d.default, {
1106+
target: \\"e1h80wsp3\\"
1107+
})();
1108+
const B3 = nonStyled(_c.default.C2);
1109+
const Mocks = [{
1110+
identifier: \\"A\\",
1111+
path: \\"a\\",
1112+
type: \\"default\\"
1113+
}, {
1114+
identifier: \\"A.B\\",
1115+
path: \\"a\\",
1116+
type: \\"default\\"
1117+
}, {
1118+
identifier: \\"A.C\\",
1119+
path: \\"a\\",
1120+
type: \\"default\\"
1121+
}, {
1122+
identifier: \\"A.D\\",
1123+
path: \\"a\\",
1124+
type: \\"default\\"
1125+
}, {
1126+
identifier: \\"C.C1\\",
1127+
path: \\"c\\",
1128+
type: \\"default\\"
1129+
}, {
1130+
identifier: \\"D\\",
1131+
path: \\"d\\",
1132+
type: \\"default\\"
1133+
}];
1134+
exports.Mocks = Mocks;"
1135+
`;
1136+
1137+
exports[`For component like source Works for alwaysMockIdentifiers without JSX opening element 3`] = `
1138+
"\\"use strict\\";
1139+
1140+
Object.defineProperty(exports, \\"__esModule\\", {
1141+
value: true
1142+
});
1143+
exports.Mocks = void 0;
1144+
1145+
var _a = _interopRequireDefault(require(\\"a\\"));
1146+
1147+
var _b = require(\\"../b\\");
1148+
1149+
var _c = _interopRequireDefault(require(\\"c\\"));
1150+
1151+
var _d = _interopRequireDefault(require(\\"d\\"));
1152+
1153+
var _styled = _interopRequireDefault(require(\\"styled\\"));
1154+
1155+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
1156+
1157+
var StyledA =
1158+
/*#__PURE__*/
1159+
(0, _styled.default)(_a.default, {
1160+
target: \\"e1h80wsp0\\"
1161+
})();
1162+
var StyledB = (0, _styled.default)(_a.default.B);
1163+
var StyledC = (0, _styled.default)(_a.default.C, {});
1164+
var StyledD =
1165+
/*#__PURE__*/
1166+
(0, _styled.default)(_a.default.D, {
1167+
target: \\"e1h80wsp1\\"
1168+
})(\\"font-size:8em;\\");
1169+
1170+
var B1 = _a.default.withComponent(_c.default.C1, {
1171+
target: \\"e1h80wsp2\\"
1172+
});
1173+
1174+
var B2 =
1175+
/*#__PURE__*/
1176+
(0, _styled.default)(_d.default, {
1177+
target: \\"e1h80wsp3\\"
1178+
})();
1179+
var B3 = nonStyled(_c.default.C2);
1180+
const Mocks = [{
1181+
identifier: \\"A\\",
1182+
path: \\"a\\",
1183+
type: \\"default\\"
1184+
}, {
1185+
identifier: \\"A.B\\",
1186+
path: \\"a\\",
1187+
type: \\"default\\"
1188+
}, {
1189+
identifier: \\"A.C\\",
1190+
path: \\"a\\",
1191+
type: \\"default\\"
1192+
}, {
1193+
identifier: \\"A.D\\",
1194+
path: \\"a\\",
1195+
type: \\"default\\"
1196+
}, {
1197+
identifier: \\"C.C1\\",
1198+
path: \\"c\\",
1199+
type: \\"default\\"
1200+
}, {
1201+
identifier: \\"D\\",
1202+
path: \\"d\\",
1203+
type: \\"default\\"
1204+
}];
1205+
exports.Mocks = Mocks;"
1206+
`;
1207+
10261208
exports[`For component like source Works for member expression without HOC 1`] = `
10271209
"import A from \\"a\\";
10281210
import * as B from \\"b\\";

src/__tests__/babel.spec.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,50 @@ describe("For component like source", () => {
556556

557557
expect(transform(source, { babelrc: false, plugins: [plugin], presets: ["@babel/react"] }).code).toMatchSnapshot();
558558
});
559+
560+
it("Works for alwaysMockIdentifiers without JSX opening element", () => {
561+
const source = `
562+
import A from "a";
563+
import { B } from "../b";
564+
import C from "c";
565+
import D from "d";
566+
import styled from "styled";
567+
568+
const StyledA = styled(A)\`\`;
569+
const StyledB = styled(A.B);
570+
const StyledC = styled(A.C, {});
571+
const StyledD = styled(A.D, {})\`font-size: 8em;\`;
572+
573+
const B1 = A.withComponent(C.C1);
574+
const B2 = styled(D) \`\`;
575+
576+
const B3 = nonStyled(C.C2);
577+
`;
578+
579+
expect(transform(source, { babelrc: false, plugins: [plugin], presets: ["@babel/react"] }).code).toMatchSnapshot();
580+
expect(transform(source, { babelrc: false, plugins: ["@babel/transform-modules-commonjs", "emotion", plugin], presets: ["@babel/react"], filename: "test.jsx" }).code).toMatchSnapshot();
581+
expect(transform(source, {
582+
babelrc: false,
583+
plugins: ["emotion", plugin],
584+
presets: [
585+
"@babel/react",
586+
["@babel/env", {
587+
targets: {
588+
browsers: [
589+
">0.25%",
590+
"not dead",
591+
"ie 11",
592+
"not op_mini all"
593+
],
594+
},
595+
// loose: true,
596+
modules: "commonjs",
597+
useBuiltIns: "usage",
598+
}]
599+
],
600+
filename: "test.jsx"
601+
}).code).toMatchSnapshot();
602+
})
559603
});
560604

561605
describe("For test like source", () => {

0 commit comments

Comments
 (0)