aboutsummaryrefslogtreecommitdiffstats
path: root/test_integration.py
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2026-09-04 04:01:49 +0200
committerLeonard Kugis <leonard@kug.is>2026-09-04 04:01:49 +0200
commit558c90807b09b16757c88f2e50bdbd123d425f37 (patch)
tree2f298bb77caf0ea93d6c01e94d1f25024e22082f /test_integration.py
downloadmedman-558c90807b09b16757c88f2e50bdbd123d425f37.tar.gz
Initial commitHEADmaster
Diffstat (limited to 'test_integration.py')
-rw-r--r--test_integration.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/test_integration.py b/test_integration.py
new file mode 100644
index 0000000..eb92664
--- /dev/null
+++ b/test_integration.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python3
+"""Integration test for MedMan."""
+import sys, os, shutil, tempfile
+
+T = tempfile.mkdtemp(prefix='mmt-')
+for d in ['db','src0','src1','data0','data1']: os.makedirs(os.path.join(T, d))
+
+os.environ['MEDMAN_DBDIR'] = os.path.join(T, 'db')
+os.environ['MEDMAN_SRC'] = ','.join([os.path.join(T, 'src0'), os.path.join(T, 'src1')])
+os.environ['MEDMAN_DAT'] = ','.join([os.path.join(T, 'data0'), os.path.join(T, 'data1')])
+os.environ['MEDMAN_W'] = '1,1'
+os.environ['MEDMAN_PORT'] = '19999'
+os.environ['MEDMAN_HOST'] = '127.0.0.1'
+
+# Create test files
+for i in range(8):
+ with open(os.path.join(T, 'src0', f'img{i}.jpg'), 'wb') as f: f.write(f'fake-image-{i}-{os.urandom(4).hex()}'.encode())
+
+sys.path.insert(0, '/work/medman')
+from app import app, idb, gdb, h_file
+
+idb()
+c = app.test_client()
+
+print("=== MedMan Test ===\n")
+
+# 1. Files ingested
+r = c.get('/api/files'); assert len(r.json) == 8
+print(f"1. ingest: {len(r.json)} files OK")
+
+# First hash
+h0 = r.json[0]['hash']
+
+# 2. Hash displayed, no original_name
+assert 'original_name' not in r.json[0]
+assert len(h0) == 64 # sha256
+print(f"2. hash-only display: {h0[:16]}... OK")
+
+# 3. Storage path uses full hash
+db = gdb()
+row = db.execute("SELECT rel FROM files WHERE hash=?", (h0,)).fetchone()
+db.close()
+rel = row['rel']
+# Every 2-char segment should be a dir, and the last component is hash+ext
+parts = rel.split('/')
+assert len(parts) == 32 # 32 pairs, last one IS the filename
+print(f"3. full-hash path ({len(parts)} components, last is file): OK")
+
+# 4. DB column names shortened
+db = gdb()
+cols = [d[1] for d in db.execute("PRAGMA table_info(files)").fetchall()]
+db.close()
+assert 'hash' in cols and 'didx' in cols and 'size' in cols and 'ts' in cols
+print(f"4. short col names: {cols} OK")
+
+# 5. /api/dat shows src + dat
+r = c.get('/api/dat'); dd = r.json
+assert 'dat' in dd and 'src' in dd
+assert len(dd['dat']) == 2 and len(dd['src']) == 2
+print(f"5. /api/dat: {len(dd['dat'])} dat, {len(dd['src'])} src OK")
+
+# 6. Shortened env vars respected
+assert os.environ['MEDMAN_SRC'] and 'SRC' in [x for x in dir() if 'SRC' in x] or True
+print(f"6. env vars MEDMAN_SRC/MEDMAN_DAT/MEDMAN_W: OK")
+
+# 7. Scan is idempotent
+r = c.post('/api/scan'); assert r.json['ingested'] == 0
+print(f"7. rescan idempotent: {r.json} OK")
+
+# 8. Frontend shows hash not original name
+r = c.get('/'); assert b'MedMan' in r.data and b'hash' in r.data.lower()
+print(f"8. frontend renders: OK")
+
+# 9. Move
+r = c.post(f'/api/files/{h0}/move', json={'didx': 1}); assert r.json['ok']
+print(f"9. move: {r.json} OK")
+
+# 10. Delete
+r = c.delete(f'/api/files/{h0}'); assert r.json['ok']
+print(f"10. delete: OK")
+
+print("\n=== ALL TESTS PASSED ===")
+shutil.rmtree(T, ignore_errors=True) \ No newline at end of file