Files
gitops/test/test.storage_test.ts
Juergen Kunz e3f67d12a3 fix(core): fix secrets scan upserts, connection health checks, and frontend improvements
- Add upsert pattern to SecretsScanService to prevent duplicate key errors on repeated scans
- Auto-test connection health on startup so status reflects reality
- Fix Actions view to read identity from appstate instead of broken localStorage hack
- Fetch both project and group secrets in parallel, add "All Scopes" filter to Secrets view
- Enable noCache on UtilityWebsiteServer to prevent stale browser cache
2026-02-24 22:50:26 +00:00

144 lines
5.3 KiB
TypeScript

import { assertEquals, assertExists } from 'https://deno.land/std@0.208.0/assert/mod.ts';
import { StorageManager } from '../ts/storage/index.ts';
import * as smartsecret from '@push.rocks/smartsecret';
Deno.test('StorageManager memory: set and get', async () => {
const sm = new StorageManager({ backend: 'memory' });
await sm.set('/test/key1', 'hello');
const result = await sm.get('/test/key1');
assertEquals(result, 'hello');
});
Deno.test('StorageManager memory: get nonexistent returns null', async () => {
const sm = new StorageManager({ backend: 'memory' });
const result = await sm.get('/missing');
assertEquals(result, null);
});
Deno.test('StorageManager memory: delete', async () => {
const sm = new StorageManager({ backend: 'memory' });
await sm.set('/test/key1', 'hello');
const deleted = await sm.delete('/test/key1');
assertEquals(deleted, true);
const result = await sm.get('/test/key1');
assertEquals(result, null);
});
Deno.test('StorageManager memory: delete nonexistent returns false', async () => {
const sm = new StorageManager({ backend: 'memory' });
const deleted = await sm.delete('/missing');
assertEquals(deleted, false);
});
Deno.test('StorageManager memory: exists', async () => {
const sm = new StorageManager({ backend: 'memory' });
assertEquals(await sm.exists('/test/key1'), false);
await sm.set('/test/key1', 'hello');
assertEquals(await sm.exists('/test/key1'), true);
});
Deno.test('StorageManager memory: list keys under prefix', async () => {
const sm = new StorageManager({ backend: 'memory' });
await sm.set('/connections/a.json', '{}');
await sm.set('/connections/b.json', '{}');
await sm.set('/other/c.json', '{}');
const keys = await sm.list('/connections/');
assertEquals(keys, ['/connections/a.json', '/connections/b.json']);
});
Deno.test('StorageManager memory: getJSON and setJSON roundtrip', async () => {
const sm = new StorageManager({ backend: 'memory' });
const data = { id: '123', name: 'test', nested: { value: 42 } };
await sm.setJSON('/data/item.json', data);
const result = await sm.getJSON<typeof data>('/data/item.json');
assertEquals(result, data);
});
Deno.test('StorageManager memory: getJSON nonexistent returns null', async () => {
const sm = new StorageManager({ backend: 'memory' });
const result = await sm.getJSON('/missing.json');
assertEquals(result, null);
});
Deno.test('StorageManager: key validation requires leading slash', async () => {
const sm = new StorageManager({ backend: 'memory' });
let threw = false;
try {
await sm.get('no-slash');
} catch {
threw = true;
}
assertEquals(threw, true);
});
Deno.test('StorageManager: key normalization strips ..', async () => {
const sm = new StorageManager({ backend: 'memory' });
await sm.set('/test/../actual/key', 'value');
// '..' segments are stripped, so key becomes /test/actual/key — wait,
// the normalizer filters out '..' segments entirely
// /test/../actual/key -> segments: ['test', 'actual', 'key'] (.. filtered)
const result = await sm.get('/test/actual/key');
assertEquals(result, 'value');
});
Deno.test('StorageManager filesystem: set, get, delete roundtrip', async () => {
const tmpDir = await Deno.makeTempDir();
const sm = new StorageManager({ backend: 'filesystem', fsPath: tmpDir });
try {
await sm.set('/test/file.txt', 'filesystem content');
const result = await sm.get('/test/file.txt');
assertEquals(result, 'filesystem content');
assertEquals(await sm.exists('/test/file.txt'), true);
const deleted = await sm.delete('/test/file.txt');
assertEquals(deleted, true);
assertEquals(await sm.get('/test/file.txt'), null);
} finally {
await Deno.remove(tmpDir, { recursive: true });
}
});
Deno.test('StorageManager filesystem: list keys', async () => {
const tmpDir = await Deno.makeTempDir();
const sm = new StorageManager({ backend: 'filesystem', fsPath: tmpDir });
try {
await sm.setJSON('/items/a.json', { id: 'a' });
await sm.setJSON('/items/b.json', { id: 'b' });
const keys = await sm.list('/items/');
assertEquals(keys, ['/items/a.json', '/items/b.json']);
} finally {
await Deno.remove(tmpDir, { recursive: true });
}
});
Deno.test('ConnectionManager with StorageManager: create and load', async () => {
const { ConnectionManager } = await import('../ts/classes/connectionmanager.ts');
const sm = new StorageManager({ backend: 'memory' });
const secret = new smartsecret.SmartSecret({ service: 'gitops-test' });
const cm = new ConnectionManager(sm, secret);
await cm.init();
// Create a connection
const conn = await cm.createConnection('test', 'gitea', 'https://gitea.example.com', 'token');
assertExists(conn.id);
assertEquals(conn.name, 'test');
assertEquals(conn.token, '***');
// Verify it's stored in StorageManager
const stored = await sm.getJSON<{ id: string }>(`/connections/${conn.id}.json`);
assertExists(stored);
assertEquals(stored.id, conn.id);
// Create a new ConnectionManager and verify it loads the connection
const cm2 = new ConnectionManager(sm, secret);
await cm2.init();
const conns = cm2.getConnections();
assertEquals(conns.length, 1);
assertEquals(conns[0].id, conn.id);
// Wait for background health checks to avoid resource leaks
await cm.healthCheckDone;
await cm2.healthCheckDone;
});