Auto-Commit: 2026-09-05 14:51:03
CI / test (push) Canceled after 0s
CI / webapp (push) Canceled after 0s

This commit is contained in:
Jannik committed 2026-09-05 14:51:03 +02:00
1 parent 62600d7762
commit 5f6afe2448
9 files changed
+348 -2

No files matched your search

+29
View File
@@ -0,0 +1,29 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2022,
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
env: {
node: true,
es2022: true,
},
rules: {
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'warn',
'no-console': 'off',
},
ignorePatterns: [
'dist/',
'node_modules/',
'webapp/dist/',
'webapp/node_modules/',
],
};
+22
View File
@@ -0,0 +1,22 @@
{"total": {"lines":{"total":879,"covered":199,"skipped":0,"pct":22.63},"statements":{"total":967,"covered":226,"skipped":0,"pct":23.37},"functions":{"total":146,"covered":38,"skipped":0,"pct":26.02},"branches":{"total":497,"covered":100,"skipped":0,"pct":20.12},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"C:\\GitHub\\Mind-o-Mat\\src\\index.ts": {"lines":{"total":0,"covered":0,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":0,"covered":0,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"C:\\GitHub\\Mind-o-Mat\\src\\ingest.ts": {"lines":{"total":58,"covered":58,"skipped":0,"pct":100},"functions":{"total":9,"covered":9,"skipped":0,"pct":100},"statements":{"total":66,"covered":65,"skipped":0,"pct":98.48},"branches":{"total":28,"covered":24,"skipped":0,"pct":85.71}}
,"C:\\GitHub\\Mind-o-Mat\\src\\llm.ts": {"lines":{"total":24,"covered":0,"skipped":0,"pct":0},"functions":{"total":3,"covered":0,"skipped":0,"pct":0},"statements":{"total":24,"covered":0,"skipped":0,"pct":0},"branches":{"total":26,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\src\\notes-api-server.ts": {"lines":{"total":52,"covered":42,"skipped":0,"pct":80.76},"functions":{"total":14,"covered":9,"skipped":0,"pct":64.28},"statements":{"total":62,"covered":48,"skipped":0,"pct":77.41},"branches":{"total":39,"covered":30,"skipped":0,"pct":76.92}}
,"C:\\GitHub\\Mind-o-Mat\\src\\vault-path.ts": {"lines":{"total":25,"covered":24,"skipped":0,"pct":96},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":26,"covered":25,"skipped":0,"pct":96.15},"branches":{"total":18,"covered":15,"skipped":0,"pct":83.33}}
,"C:\\GitHub\\Mind-o-Mat\\src\\cli\\index-cmd.ts": {"lines":{"total":215,"covered":47,"skipped":0,"pct":21.86},"functions":{"total":23,"covered":6,"skipped":0,"pct":26.08},"statements":{"total":245,"covered":56,"skipped":0,"pct":22.85},"branches":{"total":106,"covered":21,"skipped":0,"pct":19.81}}
,"C:\\GitHub\\Mind-o-Mat\\src\\cli\\index.ts": {"lines":{"total":29,"covered":0,"skipped":0,"pct":0},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":29,"covered":0,"skipped":0,"pct":0},"branches":{"total":17,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\src\\cli\\ingest.ts": {"lines":{"total":127,"covered":0,"skipped":0,"pct":0},"functions":{"total":16,"covered":0,"skipped":0,"pct":0},"statements":{"total":139,"covered":0,"skipped":0,"pct":0},"branches":{"total":84,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\src\\cli\\init-vault.ts": {"lines":{"total":78,"covered":0,"skipped":0,"pct":0},"functions":{"total":2,"covered":0,"skipped":0,"pct":0},"statements":{"total":83,"covered":0,"skipped":0,"pct":0},"branches":{"total":29,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\src\\cli\\sync.ts": {"lines":{"total":57,"covered":0,"skipped":0,"pct":0},"functions":{"total":4,"covered":0,"skipped":0,"pct":0},"statements":{"total":60,"covered":0,"skipped":0,"pct":0},"branches":{"total":20,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\App.tsx": {"lines":{"total":46,"covered":0,"skipped":0,"pct":0},"functions":{"total":19,"covered":0,"skipped":0,"pct":0},"statements":{"total":51,"covered":0,"skipped":0,"pct":0},"branches":{"total":51,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\ClusterMap.tsx": {"lines":{"total":19,"covered":0,"skipped":0,"pct":0},"functions":{"total":7,"covered":0,"skipped":0,"pct":0},"statements":{"total":19,"covered":0,"skipped":0,"pct":0},"branches":{"total":12,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\Editor.tsx": {"lines":{"total":24,"covered":0,"skipped":0,"pct":0},"functions":{"total":6,"covered":0,"skipped":0,"pct":0},"statements":{"total":26,"covered":0,"skipped":0,"pct":0},"branches":{"total":16,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\EditorWithLoad.tsx": {"lines":{"total":61,"covered":0,"skipped":0,"pct":0},"functions":{"total":15,"covered":0,"skipped":0,"pct":0},"statements":{"total":66,"covered":0,"skipped":0,"pct":0},"branches":{"total":16,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\RadialView.tsx": {"lines":{"total":25,"covered":0,"skipped":0,"pct":0},"functions":{"total":10,"covered":0,"skipped":0,"pct":0},"statements":{"total":27,"covered":0,"skipped":0,"pct":0},"branches":{"total":18,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\landkarte.ts": {"lines":{"total":4,"covered":0,"skipped":0,"pct":0},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":4,"covered":0,"skipped":0,"pct":0},"branches":{"total":3,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\main.tsx": {"lines":{"total":1,"covered":0,"skipped":0,"pct":0},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":1,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\note-loader.ts": {"lines":{"total":5,"covered":0,"skipped":0,"pct":0},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":5,"covered":0,"skipped":0,"pct":0},"branches":{"total":2,"covered":0,"skipped":0,"pct":0}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\notes-api.ts": {"lines":{"total":15,"covered":15,"skipped":0,"pct":100},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":19,"covered":18,"skipped":0,"pct":94.73},"branches":{"total":10,"covered":9,"skipped":0,"pct":90}}
,"C:\\GitHub\\Mind-o-Mat\\webapp\\src\\sync-queue.ts": {"lines":{"total":14,"covered":13,"skipped":0,"pct":92.85},"functions":{"total":6,"covered":6,"skipped":0,"pct":100},"statements":{"total":15,"covered":14,"skipped":0,"pct":93.33},"branches":{"total":2,"covered":1,"skipped":0,"pct":50}}
}
View File
Whitespace-only changes.
+144 -1
View File
@@ -19,6 +19,7 @@
"@types/node": "^22.0.0",
"@typescript-eslint/eslint-plugin": "^8.69.0",
"@typescript-eslint/parser": "^8.69.0",
"@vitest/coverage-v8": "^5.0.0",
"chokidar": "^5.0.0",
"eslint": "^9.39.5",
"eslint-config-prettier": "^10.1.8",
@@ -80,17 +81,42 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
"integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
"integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.29.8",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz",
"integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.29.8"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz",
@@ -101,6 +127,30 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.29.8",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz",
"integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.29.7",
"@babel/helper-validator-identifier": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@bcoe/v8-coverage": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz",
"integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
}
},
"node_modules/@bramus/specificity": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
@@ -1238,6 +1288,58 @@
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@vitest/coverage-v8": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-5.0.0.tgz",
"integrity": "sha512-toMg6PZGCIa/lQNCDoASrfb1ly4hsUKXFtFYC9kD4t78o5Y6LyNJU7AENt8eHPr3quYdxaxK7hj2mnbFfUk9NA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
"@vitest/istanbul-lib-coverage": "^1.0.0",
"@vitest/istanbul-lib-report": "^1.0.0",
"ast-v8-to-istanbul": "^1.0.5",
"magicast": "^0.5.4",
"obug": "^2.1.4",
"std-env": "^4.2.0",
"tinyrainbow": "^3.1.1"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
"@vitest/browser": "5.0.0",
"vitest": "5.0.0"
},
"peerDependenciesMeta": {
"@vitest/browser": {
"optional": true
}
}
},
"node_modules/@vitest/istanbul-lib-coverage": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-coverage/-/istanbul-lib-coverage-1.0.1.tgz",
"integrity": "sha512-k3DJZ8LhMBK9NS4SclF1ASD3OgXEWDorbIcPTRDK0/Zae6fRvu+fJRxtFdLfHsa9Y24beCdPnoNZ4LviTNstfA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=22"
}
},
"node_modules/@vitest/istanbul-lib-report": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@vitest/istanbul-lib-report/-/istanbul-lib-report-1.0.1.tgz",
"integrity": "sha512-1EOLRfsTMnyAr3+kEAsP4o9dhaDlGPpD7H5iLBBeq//YpNB1VIahkPhB+eRp9N2Dkfw8oySROjE3yf9XDeaIkQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vitest/istanbul-lib-coverage": "1.0.1"
},
"engines": {
"node": ">=22"
}
},
"node_modules/@vitest/mocker": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz",
@@ -1373,6 +1475,25 @@
"node": ">=12"
}
},
"node_modules/ast-v8-to-istanbul": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz",
"integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.31",
"estree-walker": "^3.0.3",
"js-tokens": "^10.0.0"
}
},
"node_modules/ast-v8-to-istanbul/node_modules/js-tokens": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz",
"integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==",
"dev": true,
"license": "MIT"
},
"node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -2630,6 +2751,18 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/magicast": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.4.tgz",
"integrity": "sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.29.7",
"@babel/types": "^7.29.7",
"source-map-js": "^1.2.1"
}
},
"node_modules/mdn-data": {
"version": "2.27.1",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
@@ -3202,6 +3335,16 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tinyrainbow": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.1.tgz",
"integrity": "sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/tldts": {
"version": "7.4.11",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.11.tgz",
+1
View File
@@ -51,6 +51,7 @@
"@types/node": "^22.0.0",
"@typescript-eslint/eslint-plugin": "^8.69.0",
"@typescript-eslint/parser": "^8.69.0",
"@vitest/coverage-v8": "^5.0.0",
"chokidar": "^5.0.0",
"eslint": "^9.39.5",
"eslint-config-prettier": "^10.1.8",
View File
Whitespace-only changes.
+135
View File
@@ -0,0 +1,135 @@
// Direkter Unit-Test fuer findSimilarGroups (v0.5)
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { findSimilarGroups } from '../src/cli/index-cmd.js';
import type { VaultNode } from '../src/cli/index-cmd.js';
const vaults: string[] = [];
afterEach(() => {
for (const v of vaults) rmSync(v, { recursive: true, force: true });
});
function setupVault(files: Record<string, string>): string {
const vault = mkdtempSync(join(tmpdir(), 'mindomat-similar-direct-'));
for (const d of [
'00_Inbox', '10_Wiki/Seiten', '01_Daily', '20_Projekte',
'99_System', '99_System/Skripte', '99_System/Logs', '99_System/Cache',
]) {
mkdirSync(join(vault, d), { recursive: true });
}
for (const [rel, content] of Object.entries(files)) {
const full = join(vault, rel);
mkdirSync(join(full, '..'), { recursive: true });
writeFileSync(full, content);
}
return vault;
}
function node(id: string, cluster = null): VaultNode {
return {
id,
title: id,
type: 'inbox',
cluster,
status: null,
created: null,
aktualisiert: null,
tags: [],
size: 0,
veraltet: false,
contentHash: 'h',
};
}
describe('findSimilarGroups direkt', () => {
it('leere Liste: keine Gruppen', () => {
const vault = setupVault({});
vaults.push(vault);
const groups = findSimilarGroups(vault, [], 0.15);
expect(groups).toEqual([]);
});
it('Notiz mit zu kurzem Body wird uebersprungen', () => {
const vault = setupVault({
'01_Daily/2026-01-01_Kurz.md': '# K',
});
vaults.push(vault);
const n = node('01_Daily/2026-01-01_Kurz.md');
const groups = findSimilarGroups(vault, [n], 0.15);
expect(groups).toEqual([]);
});
it('nicht-existierende Datei wird uebersprungen', () => {
const vault = setupVault({});
vaults.push(vault);
const n = node('00_Inbox/2026-01-01_NichtDa.md');
const groups = findSimilarGroups(vault, [n], 0.15);
expect(groups).toEqual([]);
});
it('aehnliche Notizen werden gefunden (Threshold)', () => {
const vault = setupVault({
'01_Daily/2026-09-05_A.md': `---
title: Kaffee
---
# Kaffee
Jeden Morgen trinke ich Kaffee mit Milch. Stille vor dem Tag.`,
'01_Daily/2026-09-05_B.md': `---
title: Kaffee Abends
---
# Kaffee
Abends trinke ich Kaffee mit Hafermilch. Andere Stille.`,
'01_Daily/2026-09-05_Sport.md': `---
title: Sport
---
# Sport
Ich gehe joggen im Park.`,
});
vaults.push(vault);
const nodes = [
node('01_Daily/2026-09-05_A.md'),
node('01_Daily/2026-09-05_B.md'),
node('01_Daily/2026-09-05_Sport.md'),
];
const groups = findSimilarGroups(vault, nodes, 0.15);
// Es sollte mindestens eine Gruppe geben (A und B sind aehnlich)
expect(groups.length).toBeGreaterThanOrEqual(1);
// Die aehnlichste Gruppe sollte A+B sein
const abGroup = groups.find((g) =>
g.nodes.some((n) => n.id.includes('_A.md')) &&
g.nodes.some((n) => n.id.includes('_B.md')),
);
expect(abGroup).toBeDefined();
});
it('Threshold filtert: hoeher = weniger Gruppen', () => {
const vault = setupVault({
'01_Daily/2026-09-05_A.md': `---
title: Test
---
Kaffee Tee Milch Zucker`,
'01_Daily/2026-09-05_B.md': `---
title: Test
---
Kaffee Tee Brot Butter`,
});
vaults.push(vault);
const nodes = [
node('01_Daily/2026-09-05_A.md'),
node('01_Daily/2026-09-05_B.md'),
];
const low = findSimilarGroups(vault, nodes, 0.1);
const high = findSimilarGroups(vault, nodes, 0.99);
expect(low.length).toBeGreaterThanOrEqual(high.length);
});
});
+4
View File
@@ -0,0 +1,4 @@
ERROR: Coverage for lines (22.63%) does not meet global threshold (50%)
ERROR: Coverage for functions (26.02%) does not meet global threshold (50%)
ERROR: Coverage for statements (23.37%) does not meet global threshold (50%)
ERROR: Coverage for branches (20.12%) does not meet global threshold (50%)
+13 -1
View File
@@ -1,5 +1,5 @@
// Vitest Config
// Phase 1.1 + 4.1 (jsdom fuer PWA-Editor-Tests)
// Phase 1.1 + 4.1 (jsdom fuer PWA-Editor-Tests) + Bonus (Coverage)
import { defineConfig } from 'vitest/config';
@@ -13,5 +13,17 @@ export default defineConfig({
['tests/**/sync-queue.test.ts', 'jsdom'],
],
globals: false,
coverage: {
provider: 'v8',
reporter: ['text', 'json-summary'],
include: ['src/**/*.ts', 'webapp/src/**/*.ts', 'webapp/src/**/*.tsx'],
exclude: ['src/templates/**', '**/*.test.ts', '**/*.d.ts'],
thresholds: {
lines: 50,
functions: 50,
branches: 50,
statements: 50,
},
},
},
});