I'm building a plugin for Obsidian and I setup my project from their plugin template on GitHub.
To produce a robust plugin, I want to setup unit testing with Jest. Then, I made a simple unit test for my plugin and imported the obsidian
module in the test file. However, when launching the test, it produces the following error :
FAIL tests/sync_algorithm.test.ts
● Test suite failed to run
Cannot find module 'obsidian' from 'tests/sync_algorithm.test.ts'
1 | import { syncAlgorithm } from "../src/sync_algorithm";
> 2 | import { TFile } from "obsidian";
| ^
3 |
4 | describe("Sync algorithm", () => {
5 | beforeEach(() => {});
at Resolver._throwModNotFoundError (node_modules/jest-resolve/build/resolver.js:427:11)
at Object.<anonymous> (tests/sync_algorithm.test.ts:2:1)
IDE : VS Code
Here are the important informations from the package.json
file :
{
...
"scripts": {
...
"test": "jest"
},
...
"devDependencies": {
"@codemirror/state": "^6.2.0",
"@codemirror/view": "^6.8.1",
"@types/jest": "^29.4.0",
"@types/node": "^16.18.12",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"builtin-modules": "3.3.0",
"esbuild": "0.17.3",
"eslint": "^8.34.0",
"jest": "^29.4.2",
"obsidian": "^1.1.1",
"ts-jest": "^29.0.5",
"ts-node": "^10.9.1",
"tslib": "2.4.0",
"typescript": "4.7.4"
}
}
export default {
moduleDirectories: ["node_modules", "node_modules/.pnpm", "src"],
modulePaths: ["<rootDir>"],
moduleFileExtensions: [
"js",
"mjs",
"cjs",
"jsx",
"ts",
"tsx",
"json",
"node",
],
moduleNameMapper: {
// obsidian:
// "<rootDir>//node_modules/.pnpm/obsidian@1.1.1_cknrwgf45skglbt6g7kref4zeq/node_modules/obsidian",
"./node_modules/(.*)": "<rootDir>/node_modules/$1",
},
transform: {
"^.+\\.ts$": "ts-jest",
},
};
{
"compilerOptions": {
"baseUrl": ".",
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
"target": "ES6",
"allowJs": true,
"noImplicitAny": true,
"moduleResolution": "node",
"importHelpers": true,
"isolatedModules": true,
"strictNullChecks": true,
"esModuleInterop": true,
"lib": [
"DOM",
"ES5",
"ES6",
"ES7"
]
},
"include": [
"**/*.ts"
],
}
I first installed the project using pnpm
. However, as this package manager uses symlinks for managing packages, I thought it would be the cause of the problem.
So I changed and reinstalled all dependencies using npm
. However, the bug still appeared.
I also tried yarn
but the error still there.
I tried lots of changes in the packages I use, the jest.config.ts
or jest.config.js
and the tsconfig.json
files.
I tried changing package manager and configuration according to searches I made.
Here are some already built plugins for Obsidian that use Jest for testing. I tried to reproduce their configurations :
The latter is the one I've found a jest config file and tests files that imports obsidian module. I cloned it locally and ran successfully all its tests.
But it didn't work when reproducing configs in my repo.
Here are some ressources I read to change the configuration accordingly and resolve this error :
Thank you in advance for any help or suggestion to make it working.
Why didn't you mock the module? Like:
jest.mock('./moduleName') //replace with obsidian
or parts (function / construct etc.) you want to test:
jest.mock('./moduleName', () => ({
<function>: () => jest.fn(),
}));
Example for obsidian/TFile
:
// Create a mock for the TFile class
jest.mock('obsidian', () => {
return {
TFile: jest.fn().mockImplementation(() => {
return {
// Add any methods or properties you want to mock
basename: 'mock-basename.md',
path: 'mock-path',
extension: 'md',
stat: jest.fn(),
};
}),
};
});
I would suggest this approach, because you don't need to test the library. You should aim to test the functionality of your code in isolation from external dependencies. This is because external dependencies such as libraries can be unpredictable, and their behavior can change without your knowledge, making your tests unreliable.