Refs #32: some basics testing setup with coverage

This commit is contained in:
Roland Broekema 2025-06-05 12:17:52 +02:00
parent 4c3de32a8c
commit 5c3f88a6e0
11 changed files with 3454 additions and 73 deletions

View file

@ -1,2 +1,3 @@
npm node_modules
build
build
tests/scripts

5
.gitignore vendored
View file

@ -1,5 +1,5 @@
# vscode
.vscode
.vscode
# Intellij
*.iml
@ -8,9 +8,10 @@
# npm
node_modules
# Don't include the compiled main.js file in the repo.
# Don't include the compiled files in the repo.
# They should be uploaded to GitHub releases instead.
main.js
coverage
# Exclude sourcemaps
*.map

3396
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,10 @@
"scripts": {
"dev": "node esbuild.config.mjs",
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
"version": "node version-bump.mjs && git add manifest.json versions.json"
"version": "node version-bump.mjs && git add manifest.json versions.json",
"test": "vitest",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage"
},
"keywords": [
"obsidian",
@ -16,18 +19,20 @@
"author": "",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",
"@types/node": "^22.15.29",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"@vitest/coverage-istanbul": "^3.2.1",
"builtin-modules": "3.3.0",
"esbuild": "^0.25.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"obsidian": "^1.8.7",
"tslib": "2.4.0",
"typescript": "4.7.4"
"typescript": "4.7.4",
"vitest": "^3.2.1"
},
"dependencies": {
"react": "^18.2.0",

View file

@ -1,4 +1,4 @@
import { ContactsPluginSettings } from "src/settings/settings";
import { ContactsPluginSettings } from "src/settings/settings.d";
type SettingsListener = (settings: ContactsPluginSettings) => void;
let _settings: ContactsPluginSettings | undefined

6
src/settings/settings.d.ts vendored Normal file
View file

@ -0,0 +1,6 @@
export interface ContactsPluginSettings {
contactsFolder: string;
defaultHashtag: string;
[key: string]: string|boolean;
}

View file

@ -4,12 +4,7 @@ import { InsighSettingProperties } from "src/insights/insightDefinitions";
import { insightService } from "src/insights/insightService";
import ContactsPlugin from "src/main";
import { FolderSuggest } from "src/settings/FolderSuggest";
export interface ContactsPluginSettings {
contactsFolder: string;
defaultHashtag: string;
[key: string]: string|boolean;
}
import { ContactsPluginSettings } from "src/settings/settings.d"
const insightsSetting = insightService.settings();
const insightsSettingDefaults = insightsSetting.reduce((acc:Record<string, string|boolean>, setting) => {

77
tests/contexts.spec.ts Normal file
View file

@ -0,0 +1,77 @@
import { App } from "obsidian";
import { clearApp,getApp, setApp } from 'src/context/sharedAppContext'
import {
setSettings,
getSettings,
clearSettings,
onSettingsChange,
} from 'src/context/sharedSettingsContext';
import type { ContactsPluginSettings } from 'src/settings/settings.d';
import { afterEach,describe, expect, it, vi } from 'vitest';
const mockSettings: ContactsPluginSettings = {
contactsFolder: 'Contacts',
defaultHashtag: '',
enableSync: true,
};
describe('sharedSppContext', () => {
afterEach(() => clearApp());
it('stores and retrieves the app instance', () => {
const mockApp = { vault: { name: 'test' }, workspace: { activeLeaf: true } } as unknown as App;
setApp(mockApp);
const retrieved = getApp();
expect(retrieved).toBe(mockApp);
});
it('throws if app is not set', () => {
expect(() => getApp()).toThrow('App context has not been set.');
});
});
describe('sharedSettingsContext', () => {
afterEach(() => {
clearSettings();
});
it('stores and retrieves the settings', () => {
setSettings(mockSettings);
const retrieved = getSettings();
expect(retrieved).toBe(mockSettings);
});
it('throws if settings are not set', () => {
expect(() => getSettings()).toThrow('Plugin context has not been set.');
});
it('calls listeners when settings are updated', () => {
const listener = vi.fn();
onSettingsChange(listener);
setSettings(mockSettings);
expect(listener).toHaveBeenCalledTimes(1);
expect(listener).toHaveBeenCalledWith(mockSettings);
});
it('removes listener when unsubscribe is called', () => {
const listener = vi.fn();
const unsubscribe = onSettingsChange(listener);
unsubscribe();
setSettings(mockSettings);
expect(listener).not.toHaveBeenCalled();
});
it('clears listeners and settings', () => {
const listener = vi.fn();
onSettingsChange(listener);
setSettings(mockSettings);
clearSettings();
expect(() => getSettings()).toThrow();
setSettings(mockSettings);
expect(listener).toHaveBeenCalledTimes(1);
});
});

View file

@ -1,6 +1,7 @@
{
"compilerOptions": {
"baseUrl": ".",
"sourceMap": true,
"inlineSourceMap": true,
"inlineSources": true,
"module": "ESNext",
@ -23,4 +24,4 @@
"**/*.ts",
"**/*.tsx"
]
}
}

17
vitest.config.ts Normal file
View file

@ -0,0 +1,17 @@
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['tests/**/*.spec.ts'],
globals: true,
environment: 'node',
coverage: {
provider: 'istanbul',
reporter: ['text', 'html'],
reportsDirectory: './coverage',
include: ['src/context/*.ts'],
exclude: ['src/**/*.tsx']
},
},
});