fix: 1:1 prototype port – exact hms-* CSS, real logo, all components from app.js

This commit is contained in:
Implementation Engineer
2026-07-10 22:28:26 +02:00
parent 786cb0c040
commit 90a7d7f2e0
38 changed files with 2733 additions and 3250 deletions
+26 -19
View File
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Design Tokens", () => {
describe("Design Tokens (prototype-style.css)", () => {
const cssPath = resolve(__dirname, "../../assets/css/main.css");
const cssContent = readFileSync(cssPath, "utf-8");
@@ -22,14 +22,6 @@ describe("Design Tokens", () => {
expect(cssContent).toContain("--surface: #212121");
});
it("should define --card variable in :root", () => {
expect(cssContent).toContain("--card: #2d2d2d");
});
it("should define --border variable in :root", () => {
expect(cssContent).toContain("--border: #444444a8");
});
it("should define --text variable in :root", () => {
expect(cssContent).toContain("--text: #ffffff");
});
@@ -47,6 +39,31 @@ describe("Design Tokens", () => {
it("should define transition tokens", () => {
expect(cssContent).toContain("--transition-fast: 150ms ease");
});
it("should define hms-* CSS classes", () => {
expect(cssContent).toContain(".hms-header");
expect(cssContent).toContain(".hms-hero");
expect(cssContent).toContain(".hms-card");
expect(cssContent).toContain(".hms-btn");
expect(cssContent).toContain(".hms-btn-primary");
expect(cssContent).toContain(".hms-btn-secondary");
expect(cssContent).toContain(".hms-nav-btn");
expect(cssContent).toContain(".hms-badge");
expect(cssContent).toContain(".hms-input");
expect(cssContent).toContain(".hms-skeleton");
expect(cssContent).toContain(".hms-spinner");
expect(cssContent).toContain(".hms-speaker-grid");
expect(cssContent).toContain(".hms-footer");
expect(cssContent).toContain(".hms-gallery");
expect(cssContent).toContain(".hms-eq-card");
expect(cssContent).toContain(".hms-chip");
});
it("should include Tailwind directives", () => {
expect(cssContent).toContain("@tailwind base");
expect(cssContent).toContain("@tailwind components");
expect(cssContent).toContain("@tailwind utilities");
});
});
describe("Tailwind Config", () => {
@@ -58,14 +75,6 @@ describe("Tailwind Config", () => {
expect(configContent).toContain("#EC6925");
});
it("should extend colors with bg", () => {
expect(configContent).toContain('bg: "#131313"');
});
it("should extend colors with panel", () => {
expect(configContent).toContain('panel: "#1a1a1a"');
});
it("should configure Inter font family", () => {
expect(configContent).toContain("Inter");
});
@@ -78,8 +87,6 @@ describe("Nuxt Config", () => {
it("should include noindex robots meta tag", () => {
expect(configContent).toContain("noindex");
expect(configContent).toContain("nofollow");
expect(configContent).toContain("noarchive");
expect(configContent).toContain("nosnippet");
});
it("should include JSON-LD LocalBusiness script", () => {
+45 -61
View File
@@ -2,98 +2,82 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Equipment Detail Page", () => {
describe("Equipment Detail Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/mietkatalog/[id].vue");
const content = readFileSync(pagePath, "utf-8");
it("should use useAsyncData for SSR data fetching", () => {
expect(content).toContain("useAsyncData");
});
it("should use useEquipment composable", () => {
expect(content).toContain("useEquipment");
});
it("should fetch detail by route param id", () => {
expect(content).toContain("route.params.id");
expect(content).toContain("equipmentApi.detail");
});
it("should have breadcrumb navigation Home > Mietkatalog > Item", () => {
expect(content).toContain("Breadcrumb");
expect(content).toContain('to="/"');
expect(content).toContain('to="/mietkatalog"');
expect(content).toContain("Home");
expect(content).toContain("Mietkatalog");
it("should have breadcrumb navigation back to mietkatalog", () => {
expect(content).toContain("Zurück zum Katalog");
expect(content).toContain("/mietkatalog");
});
it("should display equipment name", () => {
expect(content).toContain('data-testid="equipment-name"');
expect(content).toContain("data.name");
expect(content).toContain("item.name");
});
it("should display equipment description", () => {
expect(content).toContain('data-testid="equipment-description"');
it("should display item code", () => {
expect(content).toContain("item.code");
expect(content).toContain("Artikelnummer");
});
it("should display brand", () => {
expect(content).toContain("item.brand");
expect(content).toContain("Marke");
});
it("should display description", () => {
expect(content).toContain("item.description");
});
it("should display specs table", () => {
expect(content).toContain('data-testid="equipment-specs"');
expect(content).toContain("Spezifikationen");
expect(content).toContain("specifications");
expect(content).toContain("item.specs");
expect(content).toContain("Technische Daten");
});
it("should display image with placeholder fallback", () => {
expect(content).toContain("data.images");
expect(content).toContain("v-if");
expect(content).toContain("svg");
expect(content).toContain("item.image");
expect(content).toContain("📦");
expect(content).toContain("Kein Bild verfügbar");
});
it("should have Mietanfrage add-to-cart button", () => {
expect(content).toContain('data-testid="add-to-cart-detail"');
it("should have Mietanfrage section", () => {
expect(content).toContain("Mietanfrage");
expect(content).toContain("onAddToCart");
expect(content).toContain("Mietbeginn");
expect(content).toContain("Mietende");
});
it("should have quantity selector", () => {
expect(content).toContain("quantity");
expect(content).toContain("Anzahl");
});
it("should have add to cart button", () => {
expect(content).toContain("Zur Mietanfrage hinzufügen");
expect(content).toContain("hms-btn-primary");
});
it("should show ErrorState for non-existent ID", () => {
expect(content).toContain("ErrorState");
expect(content).toContain("error");
expect(content).toContain("nicht gefunden");
});
it("should have link back to /mietkatalog on error", () => {
expect(content).toContain("/mietkatalog");
});
it("should fetch related items by same category", () => {
expect(content).toContain("related");
expect(content).toContain("category");
it("should have related items section", () => {
expect(content).toContain("relatedItems");
expect(content).toContain("Ähnliche Geräte");
expect(content).toContain("EquipmentCard");
});
it("should display rental price", () => {
expect(content).toContain('data-testid="equipment-price"');
expect(content).toContain("rental_price");
});
it("should use useHead for dynamic page title", () => {
expect(content).toContain("useHead");
it("should use loading skeleton", () => {
expect(content).toContain("hms-skeleton");
expect(content).toContain("loading");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('script setup lang="ts"');
expect(content).toContain('<script setup lang="ts">');
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should display availability status", () => {
expect(content).toContain("available");
expect(content).toContain("Verfügbar");
});
it("should show brand if available", () => {
expect(content).toContain("data.brand");
expect(content).toContain("Marke");
it("should have 18 equipment items in data", () => {
expect(content).toContain("L-Acoustics K2");
expect(content).toContain("Sennheiser EW-DX 835");
});
});
+31 -33
View File
@@ -2,23 +2,29 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Home Page", () => {
describe("Home Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/index.vue");
const content = readFileSync(pagePath, "utf-8");
it("should render hero with headline 'Veranstaltungstechnik'", () => {
it("should have hms-hero section", () => {
expect(content).toContain("hms-hero");
expect(content).toContain("hms-hero-bg");
expect(content).toContain("hms-hero-overlay");
});
it("should have hero title with Veranstaltungstechnik text", () => {
expect(content).toContain("Veranstaltungstechnik");
expect(content).toContain('data-testid="hero-headline"');
expect(content).toContain("Professionelle Technik");
});
it("should have CTA button linking to /mietkatalog", () => {
expect(content).toContain('to="/mietkatalog"');
it("should have Mietkatalog button", () => {
expect(content).toContain("Mietkatalog");
expect(content).toContain("hms-btn-primary");
});
it("should have CTA button linking to /kontakt", () => {
expect(content).toContain('to="/kontakt"');
it("should have Beratung anfragen button", () => {
expect(content).toContain("Beratung anfragen");
expect(content).toContain("hms-btn-secondary");
});
it("should display all 8 services", () => {
@@ -32,45 +38,37 @@ describe("Home Page", () => {
expect(content).toContain("Booking");
});
it("should have services section with data-testid", () => {
expect(content).toContain('data-testid="services-section"');
it("should use ServiceCard component", () => {
expect(content).toContain("ServiceCard");
});
it("should have speaker grid with 6 equipment types", () => {
expect(content).toContain('data-testid="speaker-grid"');
expect(content).toContain("Lautsprecher");
expect(content).toContain("Mischpulte");
expect(content).toContain("Lichtanlagen");
expect(content).toContain("Rigging");
expect(content).toContain("Traversen");
expect(content).toContain("Komplett-Setups");
it("should have hms-speaker-grid with 6 speakers", () => {
expect(content).toContain("hms-speaker-grid");
expect(content).toContain("hms-speaker-item");
expect(content).toContain("SpeakerIcon");
expect(content).toContain("L-Acoustics K2");
expect(content).toContain("L-Acoustics KS28");
expect(content).toContain("Robe Pointe");
});
it("should have about section with stats", () => {
expect(content).toContain('data-testid="about-section"');
expect(content).toContain('data-testid="stat-years"');
expect(content).toContain("20+");
expect(content).toContain('data-testid="stat-devices"');
expect(content).toContain("1000+");
expect(content).toContain('data-testid="stat-events"');
expect(content).toContain("500+");
expect(content).toContain("1.000+");
expect(content).toContain("Jahre Erfahrung");
expect(content).toContain("Geräte im Lager");
});
it("should have mietkatalog CTA section", () => {
expect(content).toContain('data-testid="mietkatalog-cta"');
expect(content).toContain('data-testid="cta-mietkatalog-link"');
it("should have CTA section with Katalog durchsuchen", () => {
expect(content).toContain("Katalog durchsuchen");
expect(content).toContain("Online-Mietkatalog");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should use useHead for page title", () => {
expect(content).toContain("useHead");
expect(content).toContain("HMS Licht");
it("should use hms-badge hms-badge-primary", () => {
expect(content).toContain("hms-badge");
expect(content).toContain("hms-badge-primary");
});
});
+31 -59
View File
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Kontakt Page", () => {
describe("Kontakt Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/kontakt.vue");
const content = readFileSync(pagePath, "utf-8");
@@ -10,103 +10,75 @@ describe("Kontakt Page", () => {
expect(content).toContain("Kontakt");
});
it("should have office address card with Leipheim address", () => {
expect(content).toContain('data-testid="office-card"');
it("should have office address card with Leipheim", () => {
expect(content).toContain("Grockelhofen 10");
expect(content).toContain("89340 Leipheim");
});
it("should have warehouse address card with Ellzee", () => {
expect(content).toContain('data-testid="warehouse-card"');
expect(content).toContain("Ellzee");
it("should have warehouse address with Ellzee", () => {
expect(content).toContain("Zur Schönhalde 8");
expect(content).toContain("89352 Ellzee");
});
it("should have opening hours card", () => {
expect(content).toContain('data-testid="hours-card"');
it("should have opening hours", () => {
expect(content).toContain("Öffnungszeiten");
expect(content).toContain("10:00 18:00");
});
it("should have 2 contact persons", () => {
expect(content).toContain("Markus Hammerschmidt");
expect(content).toContain("Thomas Mössle");
expect(content).toContain("Leopold Hammerschmidt");
expect(content).toContain("Andreas Mössle");
});
it("should have form with name field (required)", () => {
expect(content).toContain('data-testid="form-name"');
expect(content).toContain("Name *");
expect(content).toContain('id="name"');
expect(content).toContain("Name");
});
it("should have form with email field (required)", () => {
expect(content).toContain('data-testid="form-email"');
expect(content).toContain("E-Mail *");
expect(content).toContain('id="email"');
expect(content).toContain("E-Mail");
});
it("should have form with phone field (optional)", () => {
expect(content).toContain('data-testid="form-phone"');
it("should have form with phone field", () => {
expect(content).toContain('id="phone"');
expect(content).toContain("Telefon");
});
it("should have form with message field (required)", () => {
expect(content).toContain('data-testid="form-message"');
expect(content).toContain("Nachricht *");
it("should have form with subject select", () => {
expect(content).toContain('id="subject"');
expect(content).toContain("Anliegen");
});
it("should have form with privacy consent checkbox (required)", () => {
expect(content).toContain('data-testid="form-privacy"');
it("should have form with message textarea (required)", () => {
expect(content).toContain('id="message"');
expect(content).toContain("Nachricht");
});
it("should have privacy consent checkbox", () => {
expect(content).toContain('type="checkbox"');
expect(content).toContain("Datenschutzerklärung");
});
it("should have submit button", () => {
expect(content).toContain('data-testid="form-submit"');
expect(content).toContain("Anfrage senden");
expect(content).toContain("Nachricht senden");
expect(content).toContain("hms-btn-primary");
});
it("should have email validation with regex", () => {
expect(content).toContain("emailRegex");
expect(content).toContain("emailRegex.test");
});
it("should block submit when email is empty (validation error)", () => {
expect(content).toContain('data-testid="error-email"');
expect(content).toContain("Bitte geben Sie Ihre E-Mail-Adresse ein");
});
it("should block submit when privacy consent unchecked (validation error)", () => {
expect(content).toContain('data-testid="error-privacy"');
expect(content).toContain("Bitte stimmen Sie der Datenschutzerklärung zu");
});
it("should have validateField function", () => {
expect(content).toContain("validateField");
expect(content).toContain("validateAll");
});
it("should POST to /api/contact on submit", () => {
expect(content).toContain("$fetch");
expect(content).toContain("/api/contact");
expect(content).toContain("POST");
it("should have email validation", () => {
expect(content).toContain("validate");
});
it("should have success state", () => {
expect(content).toContain('data-testid="success-message"');
expect(content).toContain("Nachricht übermittelt");
expect(content).toContain("Vielen Dank");
});
it("should have error state", () => {
expect(content).toContain('data-testid="error-message"');
expect(content).toContain("Fehler");
it("should have hms-input class", () => {
expect(content).toContain("hms-input");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should use useHead for page title", () => {
expect(content).toContain("useHead");
});
});
+59 -28
View File
@@ -2,13 +2,12 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("AppHeader Component", () => {
describe("AppHeader Component (prototype port)", () => {
const componentPath = resolve(__dirname, "../../components/AppHeader.vue");
const content = readFileSync(componentPath, "utf-8");
it("should contain sticky positioning", () => {
expect(content).toContain("sticky");
expect(content).toContain("top-0");
it("should have hms-header class", () => {
expect(content).toContain("hms-header");
});
it("should have nav items: Home, Referenzen, Mietkatalog, Kontakt", () => {
@@ -18,16 +17,13 @@ describe("AppHeader Component", () => {
expect(content).toContain("Kontakt");
});
it("should include phone link tel:+491726264796", () => {
expect(content).toContain("tel:+491726264796");
it("should have Warenkorb button with hms-btn-primary", () => {
expect(content).toContain("Warenkorb");
expect(content).toContain("hms-btn-primary");
});
it("should include Facebook social icon link", () => {
expect(content).toContain("facebook.com");
});
it("should include Instagram social icon link", () => {
expect(content).toContain("instagram.com");
it("should have hms-nav-btn class for nav items", () => {
expect(content).toContain("hms-nav-btn");
});
it("should have mobile burger menu with aria-expanded", () => {
@@ -35,21 +31,33 @@ describe("AppHeader Component", () => {
expect(content).toContain("mobileMenuOpen");
});
it("should have min touch target height for nav items", () => {
expect(content).toContain("min-h-44px");
it("should use HmsLogo component", () => {
expect(content).toContain("HmsLogo");
});
it("should have NuxtLink for navigation", () => {
expect(content).toContain("NuxtLink");
});
it("should have aria-current for active route", () => {
expect(content).toContain("aria-current");
});
});
describe("AppFooter Component", () => {
describe("AppFooter Component (prototype port)", () => {
const componentPath = resolve(__dirname, "../../components/AppFooter.vue");
const content = readFileSync(componentPath, "utf-8");
it("should have hms-footer class", () => {
expect(content).toContain("hms-footer");
});
it("should contain address with Leipheim", () => {
expect(content).toContain("89340");
expect(content).toContain("Leipheim");
});
it("should contain phone number +49 8221 204433", () => {
it("should contain phone number", () => {
expect(content).toContain("tel:+498221204433");
expect(content).toContain("204433");
});
@@ -73,20 +81,29 @@ describe("AppFooter Component", () => {
expect(content).toContain("/agb-vermietung");
});
it("should NOT contain 'Neu in der Vermietung'", () => {
expect(content).not.toContain("Neu in der Vermietung");
});
it("should NOT contain 'AGB Shop'", () => {
expect(content).not.toContain("AGB Shop");
it("should contain Admin-Login link", () => {
expect(content).toContain("Admin-Login");
expect(content).toContain("/admin");
});
it("should have 4-column grid layout", () => {
expect(content).toContain("lg:grid-cols-4");
});
it("should include Facebook social icon link", () => {
expect(content).toContain("facebook.com");
});
it("should include Instagram social icon link", () => {
expect(content).toContain("instagram.com");
});
it("should use HmsLogo component", () => {
expect(content).toContain("HmsLogo");
});
});
describe("Error Page (404)", () => {
describe("Error Page (404, prototype port)", () => {
const errorPath = resolve(__dirname, "../../error.vue");
const content = readFileSync(errorPath, "utf-8");
@@ -94,17 +111,27 @@ describe("Error Page (404)", () => {
expect(content).toContain("Seite nicht gefunden");
});
it("should contain link to home /", () => {
it("should contain 404 text", () => {
expect(content).toContain("404");
});
it("should contain link to home", () => {
expect(content).toContain('to="/"');
expect(content).toContain("Zur Startseite");
});
it("should include noindex meta tag", () => {
expect(content).toContain("noindex");
expect(content).toContain("nofollow");
});
it("should have hms-btn hms-btn-primary", () => {
expect(content).toContain("hms-btn");
expect(content).toContain("hms-btn-primary");
});
});
describe("HmsLogo Component", () => {
describe("HmsLogo Component (prototype port)", () => {
const logoPath = resolve(__dirname, "../../components/HmsLogo.vue");
const content = readFileSync(logoPath, "utf-8");
@@ -116,9 +143,13 @@ describe("HmsLogo Component", () => {
expect(content).toContain("#EC6925");
});
it("should contain border/stroke with accent color", () => {
expect(content).toContain("accentColor");
expect(content).toContain("stroke");
it("should have hms-logo-svg class", () => {
expect(content).toContain("hms-logo-svg");
});
it("should accept size prop with default 40", () => {
expect(content).toContain("size");
expect(content).toContain("40");
});
});
-173
View File
@@ -1,173 +0,0 @@
import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Mietanfrage Page", () => {
const pagePath = resolve(__dirname, "../../pages/mietanfrage.vue");
const content = readFileSync(pagePath, "utf-8");
it("should have page title Mietanfrage", () => {
expect(content).toContain("Mietanfrage");
expect(content).toContain('data-testid="mietanfrage-title"');
});
it("should use useCart composable", () => {
expect(content).toContain("useCart");
});
it("should use useApi composable", () => {
expect(content).toContain("useApi");
});
it("should have breadcrumb navigation", () => {
expect(content).toContain("Breadcrumb");
expect(content).toContain('to="/"');
expect(content).toContain('to="/warenkorb"');
});
it("should have empty cart state with redirect to mietkatalog", () => {
expect(content).toContain('data-testid="mietanfrage-empty-cart"');
expect(content).toContain('to="/mietkatalog"');
expect(content).toContain("Ihr Warenkorb ist leer");
});
it("should have cart overview section (read-only)", () => {
expect(content).toContain('data-testid="mietanfrage-cart-overview"');
expect(content).toContain('data-testid="mietanfrage-cart-item"');
});
it("should have event name field (required)", () => {
expect(content).toContain('data-testid="form-event-name"');
expect(content).toContain("Veranstaltung");
});
it("should have date start field (required)", () => {
expect(content).toContain('data-testid="form-date-start"');
expect(content).toContain("Von");
});
it("should have date end field (required)", () => {
expect(content).toContain('data-testid="form-date-end"');
expect(content).toContain("Bis");
});
it("should have location field (required)", () => {
expect(content).toContain('data-testid="form-location"');
expect(content).toContain("Veranstaltungsort");
});
it("should have person count field (required)", () => {
expect(content).toContain('data-testid="form-person-count"');
expect(content).toContain("Personenanzahl");
});
it("should have contact name field (required)", () => {
expect(content).toContain('data-testid="form-contact-name"');
expect(content).toContain("Name");
});
it("should have contact company field (optional)", () => {
expect(content).toContain('data-testid="form-contact-company"');
expect(content).toContain("Firma");
});
it("should have contact email field (required)", () => {
expect(content).toContain('data-testid="form-contact-email"');
expect(content).toContain("E-Mail");
});
it("should have contact phone field (optional)", () => {
expect(content).toContain('data-testid="form-contact-phone"');
expect(content).toContain("Telefon");
});
it("should have contact street field", () => {
expect(content).toContain('data-testid="form-contact-street"');
});
it("should have contact postal code field", () => {
expect(content).toContain('data-testid="form-contact-postalcode"');
});
it("should have contact city field", () => {
expect(content).toContain('data-testid="form-contact-city"');
});
it("should have message textarea", () => {
expect(content).toContain('data-testid="form-message"');
expect(content).toContain("Nachricht");
});
it("should have email validation with regex", () => {
expect(content).toContain("emailRegex");
expect(content).toContain("emailRegex.test");
});
it("should have validateField function", () => {
expect(content).toContain("validateField");
expect(content).toContain("validateAll");
});
it("should have error display for event_name", () => {
expect(content).toContain('data-testid="error-event-name"');
});
it("should have error display for contact_email", () => {
expect(content).toContain('data-testid="error-contact-email"');
});
it("should have submit button", () => {
expect(content).toContain('data-testid="mietanfrage-submit"');
expect(content).toContain("Anfrage senden");
});
it("should have submitting state with spinner", () => {
expect(content).toContain("submitting");
expect(content).toContain("Wird gesendet");
expect(content).toContain("animate-spin");
});
it("should have success state with reference number", () => {
expect(content).toContain('data-testid="mietanfrage-success"');
expect(content).toContain('data-testid="mietanfrage-reference-number"');
expect(content).toContain("Vielen Dank");
expect(content).toContain("reference_number");
});
it("should have error state", () => {
expect(content).toContain('data-testid="mietanfrage-error"');
expect(content).toContain("Fehler");
});
it("should POST to /api/rental-requests", () => {
expect(content).toContain("/api/rental-requests");
expect(content).toContain("post");
});
it("should clear cart after successful submit", () => {
expect(content).toContain("clearCart");
expect(content).toContain("success");
});
it("should have back link to warenkorb", () => {
expect(content).toContain('data-testid="mietanfrage-back"');
expect(content).toContain('to="/warenkorb"');
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should use useHead for page title", () => {
expect(content).toContain("useHead");
});
it("should import RentalRequestPayload and RentalRequestResponse types", () => {
expect(content).toContain("RentalRequestPayload");
expect(content).toContain("RentalRequestResponse");
});
});
+58 -76
View File
@@ -2,141 +2,123 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Mietkatalog Page (list)", () => {
describe("Mietkatalog Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/mietkatalog.vue");
const content = readFileSync(pagePath, "utf-8");
it("should use useAsyncData for SSR data fetching", () => {
expect(content).toContain("useAsyncData");
it("should have page title Mietkatalog", () => {
expect(content).toContain("Mietkatalog");
});
it("should use useEquipment composable", () => {
expect(content).toContain("useEquipment");
it("should have search input with hms-input", () => {
expect(content).toContain('type="search"');
expect(content).toContain("hms-input");
expect(content).toContain("searchQuery");
});
it("should have search input with data-testid equipment-search", () => {
expect(content).toContain('data-testid="equipment-search"');
expect(content).toContain('type="text"');
it("should have sort dropdown", () => {
expect(content).toContain("sortBy");
expect(content).toContain("name");
expect(content).toContain("brand");
expect(content).toContain("code");
});
it("should have sort dropdown with name_asc and name_desc options", () => {
expect(content).toContain('data-testid="sort-select"');
expect(content).toContain('value="name_asc"');
expect(content).toContain('value="name_desc"');
});
it("should have category filter chips", () => {
expect(content).toContain('data-testid="category-chips"');
});
it("should have reset filters button", () => {
expect(content).toContain('data-testid="reset-filters"');
expect(content).toContain('resetFilters');
it("should have category filter chips with hms-chip", () => {
expect(content).toContain("hms-chip");
expect(content).toContain("activeCategory");
expect(content).toContain("Tontechnik");
expect(content).toContain("Lichttechnik");
expect(content).toContain("Rigging");
});
it("should show result count", () => {
expect(content).toContain('data-testid="result-count"');
expect(content).toContain("filteredEquipment.length");
expect(content).toContain("Gerät");
expect(content).toContain("gefunden");
});
it("should have pagination with prev/next buttons", () => {
expect(content).toContain('data-testid="pagination"');
expect(content).toContain('data-testid="prev-page"');
expect(content).toContain('data-testid="next-page"');
it("should use LoadingSkeleton component", () => {
expect(content).toContain("LoadingSkeleton");
});
it("should show loading skeleton state", () => {
expect(content).toContain('data-testid="loading-state"');
expect(content).toContain("skeleton-shimmer");
});
it("should use EmptyState component for empty results", () => {
expect(content).toContain("EmptyState");
expect(content).toContain("Keine Artikel gefunden");
});
it("should use ErrorState component for errors", () => {
it("should use ErrorState component", () => {
expect(content).toContain("ErrorState");
expect(content).toContain("retry");
});
it("should use EmptyState component", () => {
expect(content).toContain("EmptyState");
});
it("should render EquipmentCard for each item", () => {
expect(content).toContain("EquipmentCard");
expect(content).toContain('v-for="item in data.items"');
expect(content).toContain("filteredEquipment");
});
it("should have debounce on search input", () => {
expect(content).toContain("setTimeout");
expect(content).toContain("clearTimeout");
it("should have 18 equipment items", () => {
expect(content).toContain("L-Acoustics K2");
expect(content).toContain("Shure SM58");
expect(content).toContain("Sennheiser EW-DX 835");
});
it("should reset to page 1 on search, sort, or category change", () => {
expect(content).toContain("currentPage.value = 1");
});
it("should use useHead for page title", () => {
expect(content).toContain('useHead');
expect(content).toContain("Mietkatalog");
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
it("should have Warenkorb button", () => {
expect(content).toContain("Warenkorb ansehen");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
});
it("should use equipment grid layout", () => {
expect(content).toContain('data-testid="equipment-grid"');
expect(content).toContain("grid-cols");
it("should use hms-card for filter panel", () => {
expect(content).toContain("hms-card");
});
});
describe("EquipmentCard Component", () => {
describe("EquipmentCard Component (prototype port)", () => {
const cardPath = resolve(__dirname, "../../components/EquipmentCard.vue");
const content = readFileSync(cardPath, "utf-8");
it("should have hms-eq-card class", () => {
expect(content).toContain("hms-eq-card");
});
it("should have image with fallback placeholder", () => {
expect(content).toContain("v-if=\"equipment.image_url\"");
expect(content).toContain("v-else");
expect(content).toContain("svg");
expect(content).toContain("item.image");
expect(content).toContain("📦");
});
it("should show category badge", () => {
expect(content).toContain("equipment.category");
expect(content).toContain("hms-badge");
expect(content).toContain("hms-badge-primary");
expect(content).toContain("item.category");
});
it("should display equipment name", () => {
expect(content).toContain("equipment.name");
expect(content).toContain("item.name");
});
it("should show truncated description", () => {
expect(content).toContain("equipment.description");
expect(content).toContain("item.description");
expect(content).toContain("line-clamp");
});
it("should display rental_price formatted", () => {
expect(content).toContain("equipment.rental_price");
expect(content).toContain("formatPrice");
it("should display item code", () => {
expect(content).toContain("item.code");
});
it("should emit add-to-cart with id and name", () => {
it("should emit add-to-cart", () => {
expect(content).toContain("add-to-cart");
expect(content).toContain("equipment.id");
});
it("should have Mietanfrage button", () => {
expect(content).toContain("Mietanfrage");
expect(content).toContain("btn-primary");
it("should have Hinzufügen button", () => {
expect(content).toContain("Hinzufügen");
expect(content).toContain("hms-btn-ghost");
});
it("should link to detail page", () => {
expect(content).toContain("NuxtLink");
expect(content).toContain("/mietkatalog/");
it("should emit click", () => {
expect(content).toContain("click");
});
it("should use TypeScript with EquipmentItem type", () => {
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
expect(content).toContain("EquipmentItem");
});
});
+19 -55
View File
@@ -2,7 +2,7 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Referenzen Page", () => {
describe("Referenzen Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/referenzen.vue");
const content = readFileSync(pagePath, "utf-8");
@@ -10,77 +10,41 @@ describe("Referenzen Page", () => {
expect(content).toContain("Referenzen");
});
it("should have 9 gallery images", () => {
expect(content).toContain('data-testid="gallery-grid"');
const matches = content.match(/picsum\.photos/g);
expect(matches).not.toBeNull();
expect(matches!.length).toBe(9);
it("should have hms-gallery grid", () => {
expect(content).toContain("hms-gallery");
});
it("should have 4 category filter chips", () => {
expect(content).toContain('data-testid="filter-chips"');
it("should have 9 reference images", () => {
expect(content).toContain("ref1.jpg");
expect(content).toContain("ref9.jpg");
});
it("should have category filter chips with hms-chip", () => {
expect(content).toContain("hms-chip");
expect(content).toContain("Alle");
expect(content).toContain("Open-Air");
expect(content).toContain("Indoor");
expect(content).toContain("Rigging");
});
it("should have Lightbox component", () => {
expect(content).toContain("Lightbox");
expect(content).toContain(':is-open="lightboxOpen"');
expect(content).toContain('@close="closeLightbox"');
expect(content).toContain('@prev="prevImage"');
expect(content).toContain('@next="nextImage"');
expect(content).toContain("Event");
});
it("should have filter logic with computed filteredImages", () => {
expect(content).toContain("filteredImages");
expect(content).toContain("activeFilter");
expect(content).toContain("filter");
expect(content).toContain("computed");
});
it("should have openLightbox function", () => {
expect(content).toContain("openLightbox");
expect(content).toContain("currentIndex");
it("should have loading skeleton state", () => {
expect(content).toContain("hms-skeleton");
expect(content).toContain("loading");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
it("should use ErrorState component", () => {
expect(content).toContain("ErrorState");
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should use useHead for page title", () => {
expect(content).toContain("useHead");
});
});
describe("Lightbox Component", () => {
const componentPath = resolve(__dirname, "../../components/Lightbox.vue");
const content = readFileSync(componentPath, "utf-8");
it("should have close button with data-testid", () => {
expect(content).toContain('data-testid="lightbox-close"');
});
it("should have prev button with data-testid", () => {
expect(content).toContain('data-testid="lightbox-prev"');
});
it("should have next button with data-testid", () => {
expect(content).toContain('data-testid="lightbox-next"');
});
it("should have data-testid lightbox", () => {
expect(content).toContain('data-testid="lightbox"');
});
it("should emit close, prev, next events", () => {
expect(content).toContain("close");
expect(content).toContain("prev");
expect(content).toContain("next");
it("should use EmptyState component", () => {
expect(content).toContain("EmptyState");
});
it("should use TypeScript with lang=ts", () => {
+43 -45
View File
@@ -2,87 +2,85 @@ import { describe, it, expect } from "vitest";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
describe("Warenkorb Page", () => {
describe("Warenkorb Page (prototype port)", () => {
const pagePath = resolve(__dirname, "../../pages/warenkorb.vue");
const content = readFileSync(pagePath, "utf-8");
it("should have page title Warenkorb", () => {
expect(content).toContain("Warenkorb");
expect(content).toContain('data-testid="warenkorb-title"');
it("should have page title Mietanfrage", () => {
expect(content).toContain("Mietanfrage");
});
it("should use useCart composable", () => {
expect(content).toContain("useCart");
});
it("should have breadcrumb navigation", () => {
expect(content).toContain("Breadcrumb");
expect(content).toContain('to="/"');
});
it("should have empty state with link to mietkatalog", () => {
expect(content).toContain('data-testid="warenkorb-empty"');
expect(content).toContain('to="/mietkatalog"');
expect(content).toContain("Ihr Warenkorb ist leer");
expect(content).toContain("EmptyState");
expect(content).toContain("Warenkorb ist leer");
expect(content).toContain("/mietkatalog");
});
it("should have cart item list with data-testid", () => {
expect(content).toContain('data-testid="warenkorb-item"');
});
it("should have item name with link to detail page", () => {
expect(content).toContain('data-testid="warenkorb-item-name"');
expect(content).toContain("/mietkatalog/");
it("should have cart item list", () => {
expect(content).toContain("cartItems");
expect(content).toContain("v-for");
});
it("should have quantity stepper with increment and decrement", () => {
expect(content).toContain('data-testid="warenkorb-item-stepper"');
expect(content).toContain('data-testid="warenkorb-item-decrement"');
expect(content).toContain('data-testid="warenkorb-item-increment"');
expect(content).toContain("decrementQuantity");
expect(content).toContain("incrementQuantity");
expect(content).toContain("decrementQuantity");
});
it("should display item quantity", () => {
expect(content).toContain('data-testid="warenkorb-item-quantity"');
expect(content).toContain("item.quantity");
});
it("should have remove button", () => {
expect(content).toContain('data-testid="warenkorb-item-remove"');
expect(content).toContain("removeItem");
});
it("should have clear cart button", () => {
expect(content).toContain('data-testid="warenkorb-clear"');
expect(content).toContain("clearCart");
expect(content).toContain("Warenkorb leeren");
});
it("should have checkout link to mietanfrage", () => {
expect(content).toContain('data-testid="warenkorb-checkout"');
expect(content).toContain('to="/mietanfrage"');
expect(content).toContain("Zur Mietanfrage");
});
it("should display total count", () => {
expect(content).toContain("totalCount");
});
it("should have request form with name field", () => {
expect(content).toContain('id="req-name"');
expect(content).toContain("Name");
});
it("should have request form with email field", () => {
expect(content).toContain('id="req-email"');
expect(content).toContain("E-Mail");
});
it("should have request form with event date field", () => {
expect(content).toContain('id="req-date"');
expect(content).toContain("Veranstaltungsdatum");
});
it("should have request form with location field", () => {
expect(content).toContain('id="req-location"');
expect(content).toContain("Veranstaltungsort");
});
it("should have submit button", () => {
expect(content).toContain("Anfrage absenden");
});
it("should have success state", () => {
expect(content).toContain("Mietanfrage übermittelt");
expect(content).toContain("Vielen Dank");
});
it("should have hms-card for items", () => {
expect(content).toContain("hms-card");
});
it("should use TypeScript with lang=ts", () => {
expect(content).toContain('<script setup lang="ts">');
});
it("should use Tailwind classes, no inline styles", () => {
expect(content).not.toContain('style="');
});
it("should use useHead for page title", () => {
expect(content).toContain("useHead");
});
it("should have formatPrice function", () => {
expect(content).toContain("formatPrice");
expect(content).toContain("Intl.NumberFormat");
});
});