Better looking testing dashboard. Still needs work though. It does not scroll correctly.
This commit is contained in:
@@ -2,213 +2,316 @@
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
import { api } from '$lib/api/api';
|
||||
import { ae_loc, ae_sess, ae_api, slct, slct_trigger } from '$lib/stores/ae_stores';
|
||||
import { ae_loc, ae_sess, ae_api, slct } from '$lib/stores/ae_stores';
|
||||
import { get_object } from '$lib/ae_api/api_get_object';
|
||||
import { post_object } from '$lib/ae_api/api_post_object';
|
||||
import {
|
||||
Database,
|
||||
Server,
|
||||
User,
|
||||
Users,
|
||||
MapPin,
|
||||
Contact,
|
||||
ShieldCheck,
|
||||
Globe,
|
||||
RefreshCcw,
|
||||
Trash2,
|
||||
Bug,
|
||||
Zap
|
||||
} from 'lucide-svelte';
|
||||
|
||||
type key_val = {
|
||||
[key: string]: any;
|
||||
};
|
||||
// Core Module Imports
|
||||
import { load_ae_obj_li__account } from '$lib/ae_core/ae_core__account';
|
||||
import { load_ae_obj_li__site, lookup_site_domain_v3 } from '$lib/ae_core/ae_core__site';
|
||||
import { load_ae_obj_li__person } from '$lib/ae_core/ae_core__person';
|
||||
import { load_ae_obj_li__address } from '$lib/ae_core/ae_core__address';
|
||||
import { load_ae_obj_li__contact } from '$lib/ae_core/ae_core__contact';
|
||||
import { load_ae_obj_li__user } from '$lib/ae_core/ae_core__user';
|
||||
import { db_core } from '$lib/ae_core/db_core';
|
||||
|
||||
let v3_test_result: any = $state(null);
|
||||
let test_result: any = $state(null);
|
||||
let test_fqdn = $state('');
|
||||
let db_counts: Record<string, number> = $state({});
|
||||
|
||||
onMount(() => {
|
||||
console.log('Testing: +page.svelte');
|
||||
onMount(async () => {
|
||||
console.log('Testing Dashboard: +page.svelte');
|
||||
await update_db_counts();
|
||||
});
|
||||
|
||||
async function update_db_counts() {
|
||||
try {
|
||||
db_counts = {
|
||||
user: await db_core.user.count(),
|
||||
person: await db_core.person.count(),
|
||||
account: await db_core.account.count(),
|
||||
address: await db_core.address.count(),
|
||||
contact: await db_core.contact.count(),
|
||||
site: await db_core.site.count()
|
||||
};
|
||||
} catch (e) {
|
||||
console.error('Failed to get DB counts:', e);
|
||||
}
|
||||
}
|
||||
|
||||
async function run_test(name: string, test_fn: () => Promise<any>) {
|
||||
test_result = 'loading...';
|
||||
try {
|
||||
const result = await test_fn();
|
||||
test_result = { test: name, timestamp: new Date().toISOString(), result };
|
||||
await update_db_counts();
|
||||
} catch (error: any) {
|
||||
test_result = { test: name, error: error.message, details: error };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SYSTEM & INFRASTRUCTURE TESTS
|
||||
*/
|
||||
|
||||
const test_site_domain_lookup = () => run_test('Site Domain Lookup', async () => {
|
||||
const fqdn = test_fqdn || window.location.host;
|
||||
return await lookup_site_domain_v3({ api_cfg: $ae_api, fqdn, log_lvl: 1 });
|
||||
});
|
||||
|
||||
const test_bootstrap_bypass = () => run_test('Bootstrap Paradox Bypass', async () => {
|
||||
const stripped_api_cfg = { base_url: $ae_api.base_url, headers: {} };
|
||||
const fqdn = test_fqdn || window.location.host;
|
||||
return await post_object({
|
||||
api_cfg: stripped_api_cfg,
|
||||
endpoint: '/v3/crud/site_domain/search',
|
||||
headers: { 'x-no-account-id': 'System Test' },
|
||||
data: { q: fqdn },
|
||||
log_lvl: 1
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* CORE HELPER TESTS
|
||||
* CORE MODULE TESTS (V3)
|
||||
*/
|
||||
|
||||
async function test_core_get_object() {
|
||||
console.log('*** test_core_get_object() ***');
|
||||
v3_test_result = 'loading...';
|
||||
|
||||
// Direct call to get_object with minimal params
|
||||
const result = await get_object({
|
||||
api_cfg: $ae_api,
|
||||
endpoint: '/crud/account/list',
|
||||
params: { limit: 1 },
|
||||
log_lvl: 2
|
||||
const test_load_accounts = () => run_test('Load Accounts', async () => {
|
||||
return await load_ae_obj_li__account({ api_cfg: $ae_api, enabled: 'all', log_lvl: 1 });
|
||||
});
|
||||
|
||||
const test_load_people = () => run_test('Load People (Account)', async () => {
|
||||
return await load_ae_obj_li__person({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
enabled: 'all',
|
||||
log_lvl: 1
|
||||
});
|
||||
});
|
||||
|
||||
v3_test_result = {
|
||||
helper: 'get_object',
|
||||
result: result
|
||||
};
|
||||
}
|
||||
|
||||
async function test_core_post_object_v3_search() {
|
||||
console.log('*** test_core_post_object_v3_search() ***');
|
||||
v3_test_result = 'loading...';
|
||||
|
||||
// Direct call to post_object for V3 search
|
||||
const result = await post_object({
|
||||
api_cfg: $ae_api,
|
||||
endpoint: '/v3/crud/event/search',
|
||||
data: { q: 'Aether' },
|
||||
params: { limit: 1 },
|
||||
log_lvl: 2
|
||||
const test_load_addresses = () => run_test('Load Addresses', async () => {
|
||||
return await load_ae_obj_li__address({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
enabled: 'all',
|
||||
log_lvl: 1
|
||||
});
|
||||
});
|
||||
|
||||
v3_test_result = {
|
||||
helper: 'post_object',
|
||||
result: result
|
||||
};
|
||||
}
|
||||
|
||||
async function test_bootstrap_paradox_bypass() {
|
||||
console.log('*** test_bootstrap_paradox_bypass() ***');
|
||||
v3_test_result = 'loading...';
|
||||
|
||||
// CRITICAL TEST: Simulate unauthenticated first visit
|
||||
// We create a STRIPPED api_cfg that has no JWT and no account_id
|
||||
const stripped_api_cfg = {
|
||||
base_url: $ae_api.base_url,
|
||||
headers: {} // NO DEFAULT HEADERS
|
||||
};
|
||||
|
||||
const fqdn = test_fqdn || window.location.host;
|
||||
|
||||
const result = await post_object({
|
||||
api_cfg: stripped_api_cfg,
|
||||
endpoint: '/v3/crud/site_domain/search',
|
||||
headers: { 'x-no-account-id': null }, // Trigger the bypass!
|
||||
data: { q: fqdn },
|
||||
log_lvl: 2
|
||||
const test_load_contacts = () => run_test('Load Contacts', async () => {
|
||||
return await load_ae_obj_li__contact({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
enabled: 'all',
|
||||
log_lvl: 1
|
||||
});
|
||||
|
||||
v3_test_result = {
|
||||
test: 'Bootstrap Paradox Bypass',
|
||||
api_cfg_used: 'STRIPPED (No default headers)',
|
||||
fqdn_tested: fqdn,
|
||||
result: result
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* V3 WRAPPER TESTS
|
||||
* USER MANAGEMENT & SCOPING TESTS
|
||||
*/
|
||||
|
||||
async function test_v3_get_id() {
|
||||
v3_test_result = 'loading...';
|
||||
const result = await api.get_ae_obj_v3({
|
||||
api_cfg: $ae_api,
|
||||
obj_type: 'event',
|
||||
obj_id: '9dv-IV-iz-LY',
|
||||
view: 'base',
|
||||
log_lvl: 1
|
||||
const test_load_users_account = () => run_test('Load Users (Account Only)', async () => {
|
||||
return await load_ae_obj_li__user({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
include_global: false,
|
||||
log_lvl: 1
|
||||
});
|
||||
v3_test_result = result;
|
||||
}
|
||||
});
|
||||
|
||||
async function test_v3_get_nested_id() {
|
||||
v3_test_result = 'loading...';
|
||||
const result = await api.get_nested_ae_obj_v3({
|
||||
api_cfg: $ae_api,
|
||||
parent_type: 'event',
|
||||
parent_id: '9dv-IV-iz-LY',
|
||||
child_type: 'event_badge',
|
||||
child_id: 'XHTX-23-20-42',
|
||||
view: 'base',
|
||||
log_lvl: 1
|
||||
const test_load_users_global = () => run_test('Load Users (Global Only)', async () => {
|
||||
return await load_ae_obj_li__user({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: null,
|
||||
include_global: true,
|
||||
log_lvl: 1
|
||||
});
|
||||
v3_test_result = result;
|
||||
}
|
||||
});
|
||||
|
||||
const test_load_users_all = () => run_test('Load Users (All)', async () => {
|
||||
return await load_ae_obj_li__user({
|
||||
api_cfg: $ae_api,
|
||||
for_obj_id: $ae_loc.account_id,
|
||||
include_global: true,
|
||||
log_lvl: 1
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* DATA LOADING MODULE TESTS
|
||||
* LOCAL DATABASE (DEXIE) TESTS
|
||||
*/
|
||||
import { load_ae_obj_li__account, load_ae_obj_id__account } from '$lib/ae_core/ae_core__account';
|
||||
import { load_ae_obj_li__site, load_ae_obj_id__site, lookup_site_domain_v3 } from '$lib/ae_core/ae_core__site';
|
||||
|
||||
async function test_site_domain_load_v3() {
|
||||
v3_test_result = 'loading...';
|
||||
const fqdn = test_fqdn || window.location.host;
|
||||
const result = await lookup_site_domain_v3({
|
||||
api_cfg: $ae_api,
|
||||
fqdn,
|
||||
log_lvl: 2
|
||||
});
|
||||
v3_test_result = result;
|
||||
}
|
||||
const clear_local_cache = () => run_test('Clear Local Cache', async () => {
|
||||
await Promise.all([
|
||||
db_core.user.clear(),
|
||||
db_core.person.clear(),
|
||||
db_core.account.clear(),
|
||||
db_core.address.clear(),
|
||||
db_core.contact.clear(),
|
||||
db_core.site.clear()
|
||||
]);
|
||||
return 'Local cache cleared successfully';
|
||||
});
|
||||
|
||||
async function test_account_v3_load() {
|
||||
v3_test_result = 'loading...';
|
||||
const account_li = await load_ae_obj_li__account({
|
||||
api_cfg: $ae_api,
|
||||
enabled: 'all',
|
||||
hidden: 'all',
|
||||
log_lvl: 2
|
||||
});
|
||||
v3_test_result = account_li;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="container h-full mx-auto p-4 gap-8 flex flex-col">
|
||||
<header class="text-center space-y-4">
|
||||
<h1 class="h1">Aether - System Testing Dashboard</h1>
|
||||
<p class="opacity-50">Comprehensive validation for API V3 and Core Helpers</p>
|
||||
<div class="container mx-auto p-4 space-y-8">
|
||||
<header class="flex justify-between items-center bg-surface-50-900-token p-6 rounded-container shadow-xl">
|
||||
<div class="space-y-1">
|
||||
<h1 class="h1 flex items-center gap-3">
|
||||
<Bug class="text-error-500" /> System Testing
|
||||
</h1>
|
||||
<p class="opacity-60">Validation dashboard for Aether Platform V3</p>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<div class="card p-2 variant-soft-secondary flex items-center gap-4 text-sm">
|
||||
<div class="flex flex-col items-center px-2">
|
||||
<span class="font-bold">{db_counts.user ?? 0}</span>
|
||||
<span class="text-[10px] uppercase">Users</span>
|
||||
</div>
|
||||
<div class="divider-vertical h-8" />
|
||||
<div class="flex flex-col items-center px-2">
|
||||
<span class="font-bold">{db_counts.person ?? 0}</span>
|
||||
<span class="text-[10px] uppercase">People</span>
|
||||
</div>
|
||||
<div class="divider-vertical h-8" />
|
||||
<button class="btn-icon btn-icon-sm" onclick={update_db_counts} title="Refresh Counts">
|
||||
<RefreshCcw size={14} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div class="grid grid-cols-1 xl:grid-cols-[1fr_400px] gap-8">
|
||||
<!-- Control Panel -->
|
||||
<section class="space-y-6">
|
||||
<div class="card p-4 space-y-4">
|
||||
<h3 class="h3">Global Parameters</h3>
|
||||
<label class="label">
|
||||
<span>Target FQDN</span>
|
||||
<input type="text" class="input" placeholder="e.g. localhost:5173" bind:value={test_fqdn} />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="card p-4 space-y-4">
|
||||
<h3 class="h3">Core Helper Verification</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button class="btn variant-filled-primary" onclick={test_core_get_object}>get_object</button>
|
||||
<button class="btn variant-filled-primary" onclick={test_core_post_object_v3_search}>post_object (Search)</button>
|
||||
<button class="btn variant-filled-error" onclick={test_bootstrap_paradox_bypass}>Bootstrap Paradox Bypass</button>
|
||||
<main class="space-y-6">
|
||||
<!-- Global Config -->
|
||||
<div class="card p-4 variant-soft-surface space-y-4">
|
||||
<header class="flex items-center gap-2 border-b border-surface-500/30 pb-2">
|
||||
<Globe size={18} />
|
||||
<h3 class="h3">Environment Config</h3>
|
||||
</header>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<label class="label">
|
||||
<span>Current Account ID</span>
|
||||
<input type="text" class="input" readonly value={$ae_loc.account_id || 'Not Set'} />
|
||||
</label>
|
||||
<label class="label">
|
||||
<span>Override FQDN (for Domain Lookup)</span>
|
||||
<input type="text" class="input" placeholder={window.location.host} bind:value={test_fqdn} />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-4 space-y-4">
|
||||
<h3 class="h3">V3 Wrapper Tests</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button class="btn variant-filled-secondary" onclick={test_v3_get_id}>Get Event</button>
|
||||
<button class="btn variant-filled-secondary" onclick={test_v3_get_nested_id}>Get Nested Badge</button>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Infra Tests -->
|
||||
<div class="card p-4 space-y-4 shadow-lg">
|
||||
<header class="flex items-center gap-2 text-primary-500">
|
||||
<Server size={18} />
|
||||
<h4 class="h4 font-bold">Infrastructure</h4>
|
||||
</header>
|
||||
<div class="flex flex-col gap-2">
|
||||
<button class="btn variant-filled-primary justify-start" onclick={test_site_domain_lookup}>
|
||||
<Zap size={14} class="mr-2" /> Lookup Site Domain
|
||||
</button>
|
||||
<button class="btn variant-ghost-error justify-start" onclick={test_bootstrap_bypass}>
|
||||
<ShieldCheck size={14} class="mr-2" /> Bootstrap Bypass Test
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Core Module Tests -->
|
||||
<div class="card p-4 space-y-4 shadow-lg">
|
||||
<header class="flex items-center gap-2 text-secondary-500">
|
||||
<Database size={18} />
|
||||
<h4 class="h4 font-bold">Core Modules (V3)</h4>
|
||||
</header>
|
||||
<div class="grid grid-cols-2 gap-2">
|
||||
<button class="btn variant-soft-secondary btn-sm" onclick={test_load_accounts}>Accounts</button>
|
||||
<button class="btn variant-soft-secondary btn-sm" onclick={test_load_people}>People</button>
|
||||
<button class="btn variant-soft-secondary btn-sm" onclick={test_load_addresses}>Addresses</button>
|
||||
<button class="btn variant-soft-secondary btn-sm" onclick={test_load_contacts}>Contacts</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Scoping -->
|
||||
<div class="card p-4 space-y-4 shadow-lg md:col-span-2">
|
||||
<header class="flex items-center gap-2 text-tertiary-500">
|
||||
<Users size={18} />
|
||||
<h4 class="h4 font-bold">User Management Scoping</h4>
|
||||
</header>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button class="btn variant-filled-tertiary" onclick={test_load_users_account}>
|
||||
<ShieldCheck size={14} class="mr-2" /> Current Account Only
|
||||
</button>
|
||||
<button class="btn variant-filled-tertiary" onclick={test_load_users_global}>
|
||||
<Globe size={14} class="mr-2" /> Global Only
|
||||
</button>
|
||||
<button class="btn variant-filled-tertiary" onclick={test_load_users_all}>
|
||||
<RefreshCcw size={14} class="mr-2" /> All (Inclusive)
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card p-4 space-y-4">
|
||||
<h3 class="h3">Module Loader Tests</h3>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<button class="btn variant-filled-tertiary" onclick={test_account_v3_load}>Load Accounts</button>
|
||||
<button class="btn variant-filled-tertiary" onclick={test_site_domain_load_v3}>Lookup Site Domain</button>
|
||||
<!-- Maintenance -->
|
||||
<div class="card p-4 variant-soft-error flex justify-between items-center">
|
||||
<div class="flex items-center gap-3">
|
||||
<Trash2 class="text-error-500" />
|
||||
<div>
|
||||
<p class="font-bold text-error-500">Local Cache Management</p>
|
||||
<p class="text-xs opacity-60">Wipe local IndexedDB tables for core objects</p>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn variant-filled-error" onclick={clear_local_cache}>Clear Local IDB</button>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<!-- Result View -->
|
||||
<section class="space-y-4">
|
||||
<div class="card p-4 h-full bg-surface-100-800-token overflow-hidden flex flex-col">
|
||||
<aside class="space-y-4">
|
||||
<div class="card p-4 h-full bg-surface-100-800-token overflow-hidden flex flex-col sticky top-4 max-h-[calc(100vh-2rem)] shadow-2xl">
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<h3 class="h3">Result View</h3>
|
||||
{#if v3_test_result === 'loading...'}
|
||||
<span class="badge variant-filled-warning animate-pulse">Processing...</span>
|
||||
{:else if v3_test_result}
|
||||
<h3 class="h3">Output</h3>
|
||||
{#if test_result === 'loading...'}
|
||||
<span class="badge variant-filled-warning animate-pulse">Running...</span>
|
||||
{:else if test_result?.error}
|
||||
<span class="badge variant-filled-error">Failed</span>
|
||||
{:else if test_result}
|
||||
<span class="badge variant-filled-success">Success</span>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="flex-1 overflow-auto bg-black/10 rounded p-2">
|
||||
{#if v3_test_result}
|
||||
<pre class="text-xs">{JSON.stringify(v3_test_result, null, 2)}</pre>
|
||||
<div class="flex-1 overflow-auto bg-black/20 rounded-container p-4 font-mono text-xs">
|
||||
{#if test_result === 'loading...'}
|
||||
<div class="placeholder animate-pulse space-y-4">
|
||||
<div class="placeholder-circle w-12" />
|
||||
<div class="placeholder-line w-full" />
|
||||
<div class="placeholder-line w-3/4" />
|
||||
</div>
|
||||
{:else if test_result}
|
||||
<pre>{JSON.stringify(test_result, null, 2)}</pre>
|
||||
{:else}
|
||||
<p class="text-center opacity-50 py-20">Execute a test to see results</p>
|
||||
<div class="flex flex-col items-center justify-center h-full opacity-30 py-20 text-center">
|
||||
<Zap size={48} class="mb-4" />
|
||||
<p>Select a validation test<br/>to begin audit</p>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user