jest-mock-external-components
Version:
Mock external React components with jest
151 lines (119 loc) • 4.66 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.mockExternalComponents = mockExternalComponents;
exports.default = void 0;
var _path = _interopRequireDefault(require("path"));
var _fs = _interopRequireDefault(require("fs"));
var _get_mocks = require("./get_mocks");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function mockExternalComponents(componentPath, testPath) {
if (!componentPath || !testPath) {
throw new Error("Either babel plugin \"jest-mock-external-components\" is not enabled or you passed non imported identifier to mockExternalComponents()");
}
let componentFullPath = "";
const tryExt = [".tsx", ".ts", ".jsx", ".js"];
if (tryExt.find(ext => componentFullPath.endsWith(ext))) {
// import with extension
try {
componentFullPath = require.resolve(componentPath, {
paths: [_path.default.dirname(testPath)]
});
} catch (_unused) {// ignore
}
} else {
// try each extension
for (const ext of tryExt) {
try {
componentFullPath = require.resolve(`${componentPath}${ext}`, {
paths: [_path.default.dirname(testPath)]
});
} catch (_unused2) {// ignore
}
}
}
if (!componentFullPath) {
return;
}
const code = _fs.default.readFileSync(componentFullPath, "utf8");
if (!code) {
return;
}
const mocks = (0, _get_mocks.getMocks)(code, testPath.endsWith(".ts") || testPath.endsWith(".tsx") ? "typescript" : "flow");
if (!mocks.length) {
return;
}
try {
// flat mocks by module path
const flattenMocks = mocks.reduce((flattened, mock) => {
const mockPath = mock.path;
if (!flattened[mockPath]) {
flattened[mockPath] = [];
}
flattened[mockPath].push({
identifier: mock.identifier,
type: mock.type
});
return flattened;
}, {});
for (const mockPath of Object.keys(flattenMocks)) {
// path.dirname("..") and path.dirname("../") will result to "."
// const mainDirPath = modulePath === "../" || modulePath === ".." ? modulePath : path.dirname(modulePath);
const mainDirPath = _path.default.dirname(componentFullPath); // if mock is relative path then calculate properly path based on test path directory
let newPath = mockPath.startsWith(".") ? _path.default.join(mainDirPath, mockPath) : mockPath;
if (flattenMocks[mockPath] && flattenMocks[mockPath].length) {
// const newPath = path.join(mainDirPath, mock.path);
jest.doMock(newPath, () => {
const actual = jest.requireActual(newPath);
let mockedModule = { ...actual
};
Object.defineProperty(mockedModule, "__esModule", {
value: true
});
const mocks = flattenMocks[mockPath];
for (const mock of mocks) {
const mockIdentifiers = mock.identifier.split("."); // drop first identifier for namespace
if (mock.type === "namespace") {
mockIdentifiers.shift();
} // import * as Comp from "./comp"; commonjs module.exports = ReactComp;
if (!mockIdentifiers.length && mock.type === "namespace") {
delete mockedModule["__esModule"];
mockedModule = mock.identifier; // Bail
break;
}
if (mock.type === "default") {
mockedModule["default"] = mock.identifier;
} else {
const mostRightIdentifier = mockIdentifiers.pop();
if (!mostRightIdentifier) {
continue;
}
if (!mockIdentifiers.length) {
// top-level export
mockedModule[mostRightIdentifier] = mostRightIdentifier;
} else {
// sub-level export, i.e. import * as E; E.A.B; -> E dropped, A is sublevel export and B is identifier name
// import { A }; A.B -> A is sublevel export
let mockedPath = mockedModule;
while (mockIdentifiers.length > 0) {
const subLevel = mockIdentifiers.shift();
mockedPath[subLevel] = { ...actual[subLevel]
};
mockedPath = mockedPath[subLevel];
}
mockedPath[mostRightIdentifier] = mostRightIdentifier;
}
}
}
return mockedModule;
});
}
}
} catch (_unused3) {
/* ignore */
}
}
var _default = mockExternalComponents;
exports.default = _default;
//# sourceMappingURL=index.js.map
;