managarten/load-tests/web-apps.js
Till JS ae04c9e194 chore(mana): citycorners + food + wardrobe aus unified-App entfernen
Citycorners-Reste vom vorherigen Sprint mit committet. food → Nutriphi,
wardrobe → Werdrobe sind als Standalone-Apps live; die mana.how-unified-
App trägt die Modul-Surfaces nicht mehr.

Gelöscht / abgebaut:
- Module: apps/mana/.../modules/{food,wardrobe} + Routen + Locales
- Landing-Apps: apps/{food,citycorners}/ Top-Level
- Backend: apps/api/src/modules/{food,wardrobe} + MCP-Tools log_meal /
  nutrition_summary, picture-routes verifyMediaOwnership-Allowlist
- shared-branding: APP_BRANDING, APP_ICONS, MANA_APPS, Logos, Onboarding
- shared-ai, mana-tool-registry, credits, shared-types/spaces,
  shared-utils/analytics, spiral-db/MANA_APP_INDEX, website-blocks
- Cross-Module: Body-CalorieWeightChart, Comic-CharacterPicker-Wardrobe,
  website-Embed wardrobe.outfits, DaySnapshot.nutrition, FoodEventType,
  MealLogged/Meal*-Streaks/Goals/Companion/Trigger, AI-Agent-Policy,
  GoalEditor MealLogged, MyDay/RitualRunner/Rules nutrition-Refs,
  Crypto-Registry meals/wardrobeGarments/wardrobeOutfits
- Generic: PlaceCategory 'food' (places + geocoding + Locales),
  spaces.ts 'food'/'wardrobe' Modul-IDs
- Infrastruktur: cloudflared, docker-compose CORS, nginx-Landing,
  prometheus-Probe, load-tests, package.json dev-Scripts,
  generate-env, mac-mini/build-landings, dependabot

Dexie v62 Migration:
- droppt meals, goals, foodFavorites, mealTags, wardrobeGarments,
  wardrobeOutfits Tabellen
- entfernt wardrobeOutfitId / wardrobeGarmentId aus images-Index
- Upgrade-Callback strippt die toten FK-Properties aus alten image-Rows

Test/Doku:
- module-registry.test.ts: Snapshot refresht auf aktuellen Stand mit
  56 Modulen (vorher 32, statisch eingefroren pre-refactor). Plus
  LEGACY_TABLES-Exclusion für nicht-mehr-registrierte Tabellen aus
  cards/citycorners/moodlit/rituals/wishes/who.
- streaks.test.ts: MealLogged-Test in TaskCompleted-Test umgebaut
- apps/mana/CLAUDE.md: food-Refs in AI-Tool-Tabelle und
  AiProposalInbox-Liste entfernt
- validate-i18n-keys.mjs + validate-no-recursive-turbo.mjs:
  existsSync-Guard, damit die Skripte mit gestaged-aber-rm'ten Dateien
  klarkommen

mana-web svelte-check 0 errors / 7436 files, betroffene Tests grün
(streaks, dashboard, module-registry), validate:pg-schema,
validate:turbo, validate:i18n-parity grün.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 12:47:33 +02:00

70 lines
2.2 KiB
JavaScript

/* eslint-disable no-undef */
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';
const errorRate = new Rate('errors');
const appLatency = new Trend('app_latency', true);
const BASE = __ENV.BASE_URL || 'http://localhost';
// All deployed SvelteKit web apps with their ports
const apps = [
{ name: 'dashboard', url: `${BASE}:5173` },
{ name: 'chat', url: `${BASE}:3000` },
{ name: 'todo', url: `${BASE}:5188` },
{ name: 'quotes', url: `${BASE}:5185` },
{ name: 'calendar', url: `${BASE}:5186` },
{ name: 'clock', url: `${BASE}:5187` },
{ name: 'contacts', url: `${BASE}:5176` },
{ name: 'storage', url: `${BASE}:5178` },
{ name: 'presi', url: `${BASE}:5180` },
{ name: 'cards', url: `${BASE}:5181` },
{ name: 'skilltree', url: `${BASE}:5183` },
{ name: 'photos', url: `${BASE}:5184` },
{ name: 'music', url: `${BASE}:5189` },
{ name: 'picture', url: `${BASE}:5174` },
{ name: 'inventory', url: `${BASE}:5191` },
];
// When testing against production, use subdomains
const prodApps = [
{ name: 'dashboard', url: 'https://mana.how' },
{ name: 'chat', url: 'https://chat.mana.how' },
{ name: 'todo', url: 'https://todo.mana.how' },
{ name: 'calendar', url: 'https://calendar.mana.how' },
{ name: 'clock', url: 'https://clock.mana.how' },
];
export const options = {
stages: [
{ duration: '30s', target: 10 }, // Ramp up
{ duration: '3m', target: 50 }, // Hold at 50 VUs
{ duration: '30s', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<2000'], // 95% under 2s
errors: ['rate<0.05'], // <5% errors
},
};
export default function () {
const targets = __ENV.BASE_URL?.startsWith('https') ? prodApps : apps;
const app = targets[Math.floor(Math.random() * targets.length)];
const res = http.get(app.url, {
tags: { app: app.name },
timeout: '10s',
});
const success = check(res, {
'status is 200': (r) => r.status === 200,
'response has body': (r) => r.body && r.body.length > 0,
'response time < 2s': (r) => r.timings.duration < 2000,
});
errorRate.add(!success);
appLatency.add(res.timings.duration, { app: app.name });
sleep(Math.random() * 2 + 0.5); // 0.5-2.5s between requests
}