diff --git a/src/App.tsx b/src/App.tsx index 00e0140..7923c4c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,7 +2,8 @@ import { Toaster } from "@/components/ui/toaster"; import { Toaster as Sonner } from "@/components/ui/sonner"; import { TooltipProvider } from "@/components/ui/tooltip"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { useEffect } from "react"; +import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom"; import { ThemeProvider } from "@/components/ThemeProvider"; import { AnalyticsProvider } from "@/components/AnalyticsProvider"; import Index from "./pages/Index"; @@ -17,6 +18,15 @@ import NotFound from "./pages/NotFound"; const queryClient = new QueryClient(); +/** Scrollt bei einem Seitenwechsel nach oben; Anker-Links (URL mit #) bleiben unberührt. */ +const ScrollToTop = () => { + const { pathname, hash } = useLocation(); + useEffect(() => { + if (!hash) window.scrollTo(0, 0); + }, [pathname, hash]); + return null; +}; + const App = () => ( @@ -24,6 +34,7 @@ const App = () => ( + } /> diff --git a/src/pages/AGB.tsx b/src/pages/AGB.tsx index 300bfe3..5ae1928 100644 --- a/src/pages/AGB.tsx +++ b/src/pages/AGB.tsx @@ -124,10 +124,10 @@ const AGB = () => {
  1. Hosting bietet WEBklar als Hosting-Abo an. Für das Hosting-Abo und das Wartungs-Abo gelten die{" "} - Vertragsbedingungen der WEBklar-Abos - {" "}mit Leistungsbeschreibung; sie gehen diesen AGB vor. + Vertragsbedingungen für die WEBklar-Abos + {" "}mit Leistungsbeschreibungen; sie gehen diesen AGB vor.
  2. -
  3. Bestehende Hostingverträge mit jährlicher Laufzeit behalten die bei ihrem Abschluss geltende Fassung dieses Moduls.
  4. +
  5. Bestehende Hosting-Verträge mit jährlicher Laufzeit behalten die bei ihrem Abschluss vereinbarten Bedingungen.
  6. WEBklar ist berechtigt, externe Anbieter (z. B. Rechenzentren) einzusetzen.
  7. WEBklar übernimmt keine Haftung für Ausfälle externer Anbieter.
@@ -194,7 +194,7 @@ const AGB = () => {
  1. Die Vergütung ergibt sich aus dem Angebot.
  2. Projektleistungen sind nach Vereinbarung fällig.
  3. -
  4. Für das Hosting-Abo und das Wartungs-Abo gelten die Zahlungsbedingungen der Vertragsbedingungen der WEBklar-Abos (monatlich im Voraus).
  5. +
  6. Für die Abos gelten die Vertragsbedingungen für die WEBklar-Abos.
{contractDivider} @@ -243,7 +243,7 @@ const AGB = () => { 12. Kündigung
    -
  1. Laufzeitverträge (z. B. Hosting, Wartung) können zum Ende der jeweiligen Laufzeit gekündigt werden. Laufzeit und Kündigung des Hosting-Abos und des Wartungs-Abos richten sich nach den Vertragsbedingungen der WEBklar-Abos (Mindestlaufzeit 12 Monate, danach jederzeit zum Ende des Abrechnungsmonats kündbar).
  2. +
  3. Laufzeitverträge können zum Ende der jeweiligen Laufzeit gekündigt werden. Laufzeit und Kündigung der Abos richten sich nach den Vertragsbedingungen für die WEBklar-Abos.
  4. Das Recht zur außerordentlichen Kündigung bleibt unberührt.
diff --git a/src/pages/HostingAbo.tsx b/src/pages/HostingAbo.tsx index 6ac517d..b83ab38 100644 --- a/src/pages/HostingAbo.tsx +++ b/src/pages/HostingAbo.tsx @@ -19,7 +19,7 @@ const leistungen = [ }, { titel: "1 E-Mail-Postfach", - text: `Mit Ihrer eigenen Domain, 5 GB Speicher, Webmail und Zugriff per Outlook oder Smartphone. Mehr Platz gibt es über den E-Mail-Zusatzspeicher: je 5 GB für 1,00 € pro Monat (${STEUER}).`, + text: `Unter Ihrer eigenen Domain, 5 GB Speicher, Webmail und Zugriff per Outlook oder Smartphone. Mehr Platz gibt es über den E-Mail-Zusatzspeicher: je 5 GB für 1,00 € pro Monat (${STEUER}).`, }, { titel: "Störungen inklusive", @@ -36,12 +36,12 @@ const HostingAbo = () => { Webklar - - - + + @@ -92,8 +92,8 @@ const HostingAbo = () => {

Updates und Pflege der Website selbst sind nicht enthalten; bei statischen Websites sind sie für den sicheren - Betrieb nicht nötig. Braucht Ihre Website dynamische Teile oder wünschen Sie laufende Pflege und eine Stunde - Arbeitszeit pro Monat, ist unser{" "} + Betrieb in der Regel nicht nötig. Braucht Ihre Website dynamische Teile oder wünschen Sie laufende Pflege und + eine Stunde Arbeitszeit pro Monat, ist unser{" "} Wartungs-Abo das Richtige.

@@ -115,9 +115,9 @@ const HostingAbo = () => {

E-Mail-Zusatzspeicher

Brauchen Sie mehr Platz für E-Mails, buchen Sie im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je - 5 GB für 1,00 € pro Monat ({STEUER}), bis zu 10 Pakete. Die Zahl der Pakete können Sie dort jederzeit erhöhen - oder verringern, solange Ihr Abo nicht gekündigt ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats. - Einzelheiten:{" "} + 5 GB für 1,00 € pro Monat ({STEUER}), bis zu 10 Pakete. Bestellen und verringern können Sie die Pakete dort, + sobald Ihr Abo begonnen hat, solange es nicht gekündigt ist und keine Zahlung offen ist. Eine Verringerung wirkt + zum Ende des Abrechnungsmonats. Einzelheiten:{" "} § 10 der Vertragsbedingungen.

@@ -127,10 +127,10 @@ const HostingAbo = () => {

Wechsel ins Wartungs-Abo

Braucht Ihre Website später dynamische Teile oder möchten Sie Pflege und Arbeitszeit dazubuchen, wechseln Sie - im Kundenportal unter „Verträge“ jederzeit ins{" "} - Wartungs-Abo, auch während der Mindestlaufzeit, solange - Ihr Hosting-Abo nicht gekündigt ist. Mit dem Wechsel beginnt eine neue Mindestlaufzeit von 12 Monaten. - Einzelheiten:{" "} + im Kundenportal unter „Verträge“ ins{" "} + Wartungs-Abo, auch während der Mindestlaufzeit: sobald + Ihr Hosting-Abo begonnen hat, solange es nicht gekündigt ist und keine Zahlung offen ist. Mit dem Wechsel + beginnt eine neue Mindestlaufzeit von 12 Monaten. Einzelheiten:{" "} § 9 der Vertragsbedingungen.

@@ -140,8 +140,8 @@ const HostingAbo = () => {

So schließen Sie das Abo ab

Das Hosting-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns - einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Dort sehen Sie danach jederzeit - Ihre Verträge und Rechnungen, buchen Zusatzspeicher und können uns Aufträge schicken. + einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Im Kundenportal sehen Sie danach + jederzeit Ihre Verträge und Rechnungen, buchen Zusatzspeicher und schicken uns Aufträge über den Chat.

{divider} @@ -149,18 +149,19 @@ const HostingAbo = () => {

Widerruf und Kündigung

- Verbraucher können den Vertrag innerhalb von 14 Tagen widerrufen; das gilt für jede Bestellung, also für das - Abo, den Wechsel ins Wartungs-Abo und den Zusatzspeicher. Bereits gezahlte Beträge erstatten wir dann nach der{" "} + Verbraucher können jede Bestellung innerhalb von 14 Tagen ab Vertragsschluss widerrufen: den Abschluss des + Abos, den Wechsel ins Wartungs-Abo und die Bestellung von Zusatzspeicher. Bereits gezahlte Beträge erstatten + wir dann nach der{" "} Widerrufsbelehrung. Kündigen können Sie online ohne Anmeldung oder per E-Mail.

{divider} @@ -168,7 +169,7 @@ const HostingAbo = () => {

Unterlagen und Kontakt

- Vertragsbedingungen der WEBklar-Abos + Vertragsbedingungen für die WEBklar-Abos {" · "} Leistungsbeschreibung A (Hosting-Abo) {" · "} @@ -182,12 +183,12 @@ const HostingAbo = () => {

- - - - - - + +
diff --git a/src/pages/WartungsAbo.tsx b/src/pages/WartungsAbo.tsx index b790833..97e0bb5 100644 --- a/src/pages/WartungsAbo.tsx +++ b/src/pages/WartungsAbo.tsx @@ -11,7 +11,7 @@ const linkClass = "text-foreground underline hover:no-underline"; const leistungen = [ { titel: "Betrieb & Pflege Ihrer Website", - text: "Hosting auf unserem Server in Deutschland, Sicherheitsupdates für Server und Website, SSL-Zertifikat, tägliche Datensicherung und Überwachung der Erreichbarkeit. Für alle Websites und Web-Anwendungen, die wir erstellt oder zur Betreuung übernommen haben, auch mit Content-Management-System, Login oder Datenbank.", + text: "Hosting auf unserem Server in Deutschland, Sicherheitsupdates für den Server und für die Software-Komponenten Ihrer Website, die wir einsetzen, SSL-Zertifikat, tägliche Datensicherung und Überwachung der Erreichbarkeit. Für alle Websites und Web-Anwendungen, die wir erstellt oder zur Betreuung übernommen haben, auch mit Content-Management-System, Login oder Datenbank.", }, { titel: "1 Domain inklusive", @@ -36,12 +36,12 @@ const WartungsAbo = () => { Webklar - - - + + @@ -92,10 +92,11 @@ const WartungsAbo = () => {

E-Mail-Postfächer und Zusatzspeicher

Im Wartungs-Abo richten wir Ihnen beliebig viele Postfächer unter Ihrer Domain ein, mit zusammen 5 GB - Speicher. Wie der Speicher auf die Postfächer verteilt wird, bestimmen Sie. Brauchen Sie mehr - Platz, buchen Sie im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je 5 GB für 1,00 € pro Monat - ({STEUER}), bis zu 10 Pakete. Die Zahl der Pakete können Sie dort jederzeit erhöhen oder verringern, solange - Ihr Abo nicht gekündigt ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats. Einzelheiten:{" "} + Speicher. Wie der Speicher auf die Postfächer verteilt wird, bestimmen Sie. Brauchen Sie mehr Platz, buchen Sie + im Kundenportal unter „Verträge“ Zusatzspeicher: Pakete von je 5 GB für 1,00 € pro Monat ({STEUER}), bis zu + 10 Pakete. Bestellen und verringern können Sie die Pakete dort, sobald Ihr Abo begonnen hat, solange es nicht + gekündigt ist und keine Zahlung offen ist. Eine Verringerung wirkt zum Ende des Abrechnungsmonats. + Einzelheiten:{" "} § 10 der Vertragsbedingungen.

@@ -106,8 +107,11 @@ const WartungsAbo = () => {

Sie haben eine statische Website und brauchen weder Pflege noch Arbeitszeit? Dann genügt vielleicht unser{" "} Hosting-Abo für 15,00 € pro Monat ({STEUER}). Vom - Hosting- ins Wartungs-Abo können Sie jederzeit wechseln; ein Wechsel vom Wartungs- ins Hosting-Abo ist auf - Anfrage nach Ablauf der Mindestlaufzeit möglich. + Hosting- ins Wartungs-Abo wechseln Sie im Kundenportal, sobald das Hosting-Abo begonnen hat, solange es nicht + gekündigt ist und keine Zahlung offen ist; mit dem Wechsel beginnt eine neue Mindestlaufzeit von 12 Monaten. + Ein Wechsel vom Wartungs- ins Hosting-Abo ist auf Anfrage nach Ablauf der Mindestlaufzeit zum Ende eines + Abrechnungsmonats möglich, wenn Ihre Website statisch ist. Einzelheiten in{" "} + § 9 der Vertragsbedingungen.

{divider} @@ -116,8 +120,8 @@ const WartungsAbo = () => {

So schließen Sie das Abo ab

Das Wartungs-Abo schließen Sie in unserem Kundenportal ab. Den Zugang richten wir Ihnen ein, sprechen Sie uns - einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Dort sehen Sie danach jederzeit - Ihr Stundenkontingent, Ihre Rechnungen und können uns Aufträge schicken. + einfach an. Nach der Anmeldung finden Sie das Angebot im Bereich „Verträge“. Im Kundenportal sehen Sie danach + jederzeit Ihr Stundenkontingent und Ihre Rechnungen und schicken uns Aufträge über den Chat.

{divider} @@ -125,18 +129,19 @@ const WartungsAbo = () => {

Widerruf und Kündigung

- Verbraucher können den Vertrag innerhalb von 14 Tagen widerrufen; das gilt für jede Bestellung, also für das - Abo und den Zusatzspeicher. Bereits gezahlte Beträge erstatten wir dann nach der{" "} + Verbraucher können jede Bestellung innerhalb von 14 Tagen ab Vertragsschluss widerrufen: den Abschluss des + Abos, den Wechsel ins Wartungs-Abo und die Bestellung von Zusatzspeicher. Bereits gezahlte Beträge erstatten + wir dann nach der{" "} Widerrufsbelehrung. Kündigen können Sie online ohne Anmeldung oder per E-Mail.

{divider} @@ -144,7 +149,7 @@ const WartungsAbo = () => {

Unterlagen und Kontakt

- Vertragsbedingungen der WEBklar-Abos + Vertragsbedingungen für die WEBklar-Abos {" · "} Leistungsbeschreibung B (Wartungs-Abo) {" · "} @@ -158,12 +163,12 @@ const WartungsAbo = () => {

- - - - - - + +
diff --git a/src/test/abos.test.tsx b/src/test/abos.test.tsx index cd8e687..2c503a7 100644 --- a/src/test/abos.test.tsx +++ b/src/test/abos.test.tsx @@ -1,17 +1,27 @@ import { describe, it, expect } from "vitest"; -import { render, screen } from "@testing-library/react"; +import { render, screen, within } from "@testing-library/react"; import { MemoryRouter } from "react-router-dom"; import HostingAbo from "@/pages/HostingAbo"; import WartungsAbo from "@/pages/WartungsAbo"; import AGB from "@/pages/AGB"; +// Dieselben Future-Flags wie der BrowserRouter in App.tsx, sonst warnt React Router in der Testausgabe. +const routerFuture = { v7_startTransition: true, v7_relativeSplatPath: true }; + // Texte, die auf einer Seite mehrfach vorkommen können, werden mit getAllByText // geprüft (getByText wirft bei mehreren Treffern); Abwesenheit mit queryAllByText. +/** Liefert den
-Abschnitt zu einer Überschrift. */ +const sectionOf = (name: string | RegExp): HTMLElement => { + const section = screen.getByRole("heading", { name }).closest("section"); + if (!section) throw new Error(`Abschnitt zur Überschrift ${String(name)} fehlt`); + return section; +}; + describe("Abo-Seiten", () => { it("Hosting-Abo-Seite: Preis, Postfach, Links", () => { render( - + , ); @@ -27,25 +37,63 @@ describe("Abo-Seiten", () => { ); }); + it("Hosting-Abo-Seite: Wechsel und Zusatzspeicher nur unter den Bedingungen des Portals", () => { + render( + + + , + ); + // § 9 Abs. 1: Wechsel nur, wenn das Hosting-Abo begonnen hat, nicht gekündigt ist und keine Zahlung offen ist; + // mit dem Wechsel beginnt eine neue Mindestlaufzeit. + const wechsel = within(sectionOf("Wechsel ins Wartungs-Abo")); + expect(wechsel.getAllByText(/begonnen hat/).length).toBeGreaterThan(0); + expect(wechsel.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0); + expect(wechsel.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0); + expect(wechsel.getAllByText(/neue Mindestlaufzeit von 12 Monaten/).length).toBeGreaterThan(0); + // § 10 Abs. 1: dieselben Bedingungen für Bestellung und Verringerung des Zusatzspeichers. + const speicher = within(sectionOf("E-Mail-Zusatzspeicher")); + expect(speicher.getAllByText(/begonnen hat/).length).toBeGreaterThan(0); + expect(speicher.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0); + expect(speicher.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0); + }); + it("Wartungs-Abo-Seite: beliebig viele Postfächer, Zusatzspeicher", () => { render( - + , ); + expect(screen.getAllByText("Beliebig viele Postfächer").length).toBeGreaterThan(0); expect(screen.getAllByText(/beliebig viele Postfächer/).length).toBeGreaterThan(0); expect(screen.queryAllByText("1 E-Mail-Postfach").length).toBe(0); expect(screen.queryAllByText(/1 E-Mail-Postfach/).length).toBe(0); expect(screen.getAllByText(/1,00 €/).length).toBeGreaterThan(0); + // Wechsel und Zusatzspeicher auch hier nur unter den Bedingungen des Portals. + const speicher = within(sectionOf("E-Mail-Postfächer und Zusatzspeicher")); + expect(speicher.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0); + expect(speicher.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0); + const hosting = within(sectionOf("Hosting-Abo für statische Websites")); + expect(hosting.getAllByText(/nicht gekündigt/).length).toBeGreaterThan(0); + expect(hosting.getAllByText(/keine Zahlung offen/).length).toBeGreaterThan(0); + expect(hosting.getAllByText(/neue Mindestlaufzeit von 12 Monaten/).length).toBeGreaterThan(0); + expect(hosting.getByRole("link", { name: /§ 9 der Vertragsbedingungen/ })).toHaveAttribute( + "href", + "https://project.webklar.com/abo-bedingungen.html#wechsel", + ); }); it("AGB Modul C verweist auf das Hosting-Abo", () => { render( - + , ); - expect(screen.getAllByText(/Hosting-Abo/).length).toBeGreaterThan(0); + const modulC = within(sectionOf(/Leistungsmodul C/)); + expect(modulC.getAllByText(/Hosting-Abo/).length).toBeGreaterThan(0); + expect(modulC.getByRole("link", { name: "Vertragsbedingungen für die WEBklar-Abos" })).toHaveAttribute( + "href", + "https://project.webklar.com/abo-bedingungen.html", + ); expect(screen.queryAllByText(/verlängern sich automatisch/).length).toBe(0); }); });