feat: Google Apps Script für automatische Test-Formular-Erstellung
- Automatische Generierung eines Google Forms aus der Test-Checkliste - ~180 Checkbox-Items über 14 Sections - Testergebnis-Bereich mit Fehlerberichten und Gesamtbewertung - Kein API-Key erforderlich - läuft direkt im Google Account - Schritt-für-Schritt-Anleitung im Code-Kommentar - Exportierbar nach Google Sheets - Mehrfach verwendbar für verschiedene Test-Runden
This commit is contained in:
422
docs/google-apps-script-test-form.js
Normal file
422
docs/google-apps-script-test-form.js
Normal file
@@ -0,0 +1,422 @@
|
||||
/**
|
||||
* Google Apps Script zur automatischen Erstellung eines Test-Formulars
|
||||
* für die Kunden-Statusseite
|
||||
*
|
||||
* ANLEITUNG:
|
||||
* 1. Öffne https://script.google.com/
|
||||
* 2. Klicke auf "Neues Projekt"
|
||||
* 3. Kopiere diesen Code in den Editor
|
||||
* 4. Klicke auf "Ausführen" (Play-Button) → Funktion "createTestForm"
|
||||
* 5. Erlaube die benötigten Berechtigungen
|
||||
* 6. Nach Ausführung wird die URL des erstellten Formulars in den Logs angezeigt
|
||||
* 7. Öffne die URL oder finde das Formular in Google Drive
|
||||
*/
|
||||
|
||||
function createTestForm() {
|
||||
// Erstelle neues Formular
|
||||
const form = FormApp.create('Test-Checkliste: Kunden-Statusseite');
|
||||
|
||||
// Formular-Einstellungen
|
||||
form.setDescription('Blackbox-Tests für das Feature "Token-basierte Buchungsübersicht"\n\nBranch: Statusseite\nDatum: 2025-10-01');
|
||||
form.setConfirmationMessage('Vielen Dank! Die Testergebnisse wurden gespeichert.');
|
||||
form.setAllowResponseEdits(true);
|
||||
form.setShowLinkToRespondAgain(false);
|
||||
|
||||
// Sammle E-Mail-Adressen
|
||||
form.setCollectEmail(true);
|
||||
|
||||
// === VORBEREITUNG ===
|
||||
addSection(form, 'Vorbereitung', 'Stelle sicher, dass die Testumgebung bereit ist');
|
||||
addCheckboxes(form, [
|
||||
'Entwicklungsserver läuft (pnpm dev)',
|
||||
'E-Mail-Service konfiguriert (RESEND_API_KEY gesetzt)',
|
||||
'Admin-Account verfügbar',
|
||||
'Testbehandlungen vorhanden',
|
||||
'Verfügbare Slots erstellt'
|
||||
]);
|
||||
|
||||
// === 1. BUCHUNGSERSTELLUNG & TOKEN-GENERIERUNG ===
|
||||
addSection(form, '1. Buchungserstellung & Token-Generierung', 'Teste die Token-Erstellung bei neuen Buchungen');
|
||||
|
||||
addParagraph(form, '1.1 Neue Buchung (Status: pending)');
|
||||
addCheckboxes(form, [
|
||||
'Buchung über Formular erstellen',
|
||||
'Pending-E-Mail erhalten',
|
||||
'Status-Link (/booking/{token}) in E-Mail vorhanden',
|
||||
'Button "Status ansehen" vorhanden und korrekt verlinkt',
|
||||
'Link funktioniert beim Klick'
|
||||
]);
|
||||
|
||||
addParagraph(form, '1.2 Token-Validierung');
|
||||
addCheckboxes(form, [
|
||||
'Gültiger Token öffnet Statusseite',
|
||||
'Ungültiger Token zeigt Fehlermeldung',
|
||||
'Abgelaufener Token zeigt entsprechende Meldung',
|
||||
'Token ohne Parameter zeigt Fehler'
|
||||
]);
|
||||
|
||||
// === 2. STATUSSEITE UI/UX ===
|
||||
addSection(form, '2. Statusseite UI/UX (Allgemein)', 'Teste das generelle Layout und Design');
|
||||
|
||||
addParagraph(form, '2.1 Layout & Design');
|
||||
addCheckboxes(form, [
|
||||
'Logo wird angezeigt',
|
||||
'Seite ist responsive (Desktop, Tablet, Mobile)',
|
||||
'Alle Texte sind auf Deutsch',
|
||||
'Farben entsprechen dem Branding (Pink/Purple)',
|
||||
'"Zurück zur Startseite" Link funktioniert'
|
||||
]);
|
||||
|
||||
addParagraph(form, '2.2 Navigation');
|
||||
addCheckboxes(form, [
|
||||
'Link zur Startseite funktioniert',
|
||||
'Browser-Zurück-Button funktioniert korrekt',
|
||||
'URL ist teilbar (Copy & Paste)'
|
||||
]);
|
||||
|
||||
// === 3. STATUS: PENDING ===
|
||||
addSection(form, '3. Status: Pending', 'Teste den Status "Wartet auf Bestätigung"');
|
||||
|
||||
addParagraph(form, '3.1 Anzeige');
|
||||
addCheckboxes(form, [
|
||||
'Status-Badge zeigt "⏳ Wartet auf Bestätigung" (gelb)',
|
||||
'Banner mit gelber Hintergrundfarbe',
|
||||
'Text erklärt, dass Termin geprüft wird',
|
||||
'Datum im Format dd.mm.yyyy',
|
||||
'Uhrzeit wird angezeigt',
|
||||
'Behandlung wird angezeigt',
|
||||
'Dauer in Minuten wird angezeigt',
|
||||
'Preis wird angezeigt (wenn > 0)',
|
||||
'Kundenname wird angezeigt',
|
||||
'E-Mail wird angezeigt',
|
||||
'Telefon wird angezeigt',
|
||||
'Notizen werden angezeigt (falls vorhanden)'
|
||||
]);
|
||||
|
||||
addParagraph(form, '3.2 Stornierung');
|
||||
addCheckboxes(form, [
|
||||
'Stornierungsbereich ist NICHT sichtbar',
|
||||
'Keine Stornierungsbuttons vorhanden'
|
||||
]);
|
||||
|
||||
// === 4. STATUS: CONFIRMED ===
|
||||
addSection(form, '4. Status: Confirmed', 'Teste den Status "Bestätigt"');
|
||||
|
||||
addParagraph(form, '4.1 Statuswechsel');
|
||||
addCheckboxes(form, [
|
||||
'Admin bestätigt Buchung',
|
||||
'Confirmed-E-Mail wird versendet',
|
||||
'E-Mail enthält "Termin verwalten" Button',
|
||||
'Link in E-Mail zeigt auf /booking/{token}',
|
||||
'ICS-Datei ist im E-Mail-Anhang',
|
||||
'AGB-PDF ist im E-Mail-Anhang'
|
||||
]);
|
||||
|
||||
addParagraph(form, '4.2 Anzeige');
|
||||
addCheckboxes(form, [
|
||||
'Status-Badge zeigt "✓ Bestätigt" (grün)',
|
||||
'Banner mit grüner Hintergrundfarbe',
|
||||
'Text bestätigt den Termin',
|
||||
'"Verbleibende Zeit" wird angezeigt',
|
||||
'Stunden bis zum Termin korrekt berechnet'
|
||||
]);
|
||||
|
||||
addParagraph(form, '4.3 Stornierung (wenn möglich)');
|
||||
addCheckboxes(form, [
|
||||
'Stornierungsbereich ist sichtbar',
|
||||
'Hinweistext zur Stornierungsfrist angezeigt',
|
||||
'Button "Termin stornieren" vorhanden',
|
||||
'Klick zeigt Bestätigungsdialog',
|
||||
'Dialog enthält Warnhinweis in rot',
|
||||
'Dialog hat "Ja, stornieren" Button',
|
||||
'Dialog hat "Abbrechen" Button',
|
||||
'"Abbrechen" schließt Dialog ohne Aktion',
|
||||
'"Ja, stornieren" führt Stornierung durch',
|
||||
'Nach Stornierung: Erfolgsmeldung angezeigt',
|
||||
'Nach Stornierung: Status aktualisiert'
|
||||
]);
|
||||
|
||||
addParagraph(form, '4.4 Stornierung (nicht mehr möglich)');
|
||||
addCheckboxes(form, [
|
||||
'Termin < 24h: Kein Stornierungsbutton',
|
||||
'Gelber Hinweiskasten wird angezeigt',
|
||||
'Text erklärt abgelaufene Frist',
|
||||
'Kontakthinweis wird angezeigt'
|
||||
]);
|
||||
|
||||
// === 5. STATUS: CANCELLED ===
|
||||
addSection(form, '5. Status: Cancelled', 'Teste den Status "Storniert"');
|
||||
|
||||
addParagraph(form, '5.1 Nach Stornierung');
|
||||
addCheckboxes(form, [
|
||||
'Status-Badge zeigt "✕ Storniert" (rot)',
|
||||
'Banner mit roter Hintergrundfarbe',
|
||||
'Text erklärt Stornierung',
|
||||
'Hinweis auf Neubuchung vorhanden',
|
||||
'Stornierungsbereich nicht mehr sichtbar'
|
||||
]);
|
||||
|
||||
addParagraph(form, '5.2 Cancelled-E-Mail');
|
||||
addCheckboxes(form, [
|
||||
'E-Mail wird an Kunden gesendet',
|
||||
'E-Mail enthält storniertes Datum',
|
||||
'E-Mail enthält Hinweis auf Neubuchung'
|
||||
]);
|
||||
|
||||
// === 6. STATUS: COMPLETED ===
|
||||
addSection(form, '6. Status: Completed', 'Teste den Status "Abgeschlossen"');
|
||||
addCheckboxes(form, [
|
||||
'Status-Badge zeigt "✓ Abgeschlossen" (grau)',
|
||||
'Banner mit grauer Hintergrundfarbe',
|
||||
'Dankestext wird angezeigt',
|
||||
'Stornierungsbereich nicht sichtbar',
|
||||
'Alle Termin-Details bleiben sichtbar'
|
||||
]);
|
||||
|
||||
// === 7. E-MAIL-INTEGRATION ===
|
||||
addSection(form, '7. E-Mail-Integration', 'Teste alle E-Mail-Typen');
|
||||
|
||||
addParagraph(form, '7.1 Pending-Mail');
|
||||
addCheckboxes(form, [
|
||||
'Betreff: "Deine Terminanfrage ist eingegangen"',
|
||||
'Orangefarbener "Status ansehen" Button',
|
||||
'Link funktioniert',
|
||||
'Text erklärt folgende Bestätigung',
|
||||
'Rechtliche Informationen enthalten'
|
||||
]);
|
||||
|
||||
addParagraph(form, '7.2 Confirmed-Mail');
|
||||
addCheckboxes(form, [
|
||||
'Betreff: "Dein Termin wurde bestätigt - AGB im Anhang"',
|
||||
'Pinker "Termin ansehen & verwalten" Button',
|
||||
'Link zeigt auf /booking/{token}',
|
||||
'ICS-Datei im Anhang: "Termin_Stargirlnails.ics"',
|
||||
'ICS-Datei kann in Kalender importiert werden',
|
||||
'AGB-PDF im Anhang: "AGB_Stargirlnails_Kiel.pdf"'
|
||||
]);
|
||||
|
||||
addParagraph(form, '7.3 Cancelled-Mail');
|
||||
addCheckboxes(form, [
|
||||
'Betreff: "Dein Termin wurde abgesagt"',
|
||||
'Text erklärt Stornierung',
|
||||
'Hinweis auf Neubuchung',
|
||||
'Rechtliche Informationen enthalten'
|
||||
]);
|
||||
|
||||
// === 8. ICS-KALENDEREINTRÄGE ===
|
||||
addSection(form, '8. ICS-Kalendereinträge', 'Teste die Kalenderdatei-Funktionalität');
|
||||
|
||||
addParagraph(form, '8.1 ICS-Datei Inhalt');
|
||||
addCheckboxes(form, [
|
||||
'Zeitzone: Europe/Berlin',
|
||||
'Startzeit korrekt',
|
||||
'Endzeit korrekt (Start + Behandlungsdauer)',
|
||||
'Titel: "{Behandlung} - Stargirlnails Kiel"',
|
||||
'Location: "Stargirlnails Kiel"',
|
||||
'Beschreibung enthalten',
|
||||
'24h-Erinnerung konfiguriert'
|
||||
]);
|
||||
|
||||
addParagraph(form, '8.2 Kalender-Import');
|
||||
addCheckboxes(form, [
|
||||
'Import in Kalender-App funktioniert',
|
||||
'Termin erscheint mit korrekter Zeit',
|
||||
'Erinnerung wird ausgelöst'
|
||||
]);
|
||||
|
||||
// === 9. STORNIERUNGSLOGIK ===
|
||||
addSection(form, '9. Stornierungslogik', 'Teste die Stornierungsregeln');
|
||||
|
||||
addParagraph(form, '9.1 Zeitbasierte Validierung');
|
||||
addCheckboxes(form, [
|
||||
'Termin > 24h: Stornierung möglich',
|
||||
'Termin < 24h: Stornierung nicht möglich',
|
||||
'Termin in Vergangenheit: nicht möglich',
|
||||
'Verbleibende Stunden korrekt berechnet'
|
||||
]);
|
||||
|
||||
addParagraph(form, '9.2 Statusbasierte Validierung');
|
||||
addCheckboxes(form, [
|
||||
'Status "pending": Keine Stornierung',
|
||||
'Status "confirmed": Stornierung möglich (wenn Zeit OK)',
|
||||
'Status "cancelled": Keine Stornierung',
|
||||
'Status "completed": Keine Stornierung'
|
||||
]);
|
||||
|
||||
addParagraph(form, '9.3 Stornierungsablauf');
|
||||
addCheckboxes(form, [
|
||||
'Bestätigungsdialog erscheint',
|
||||
'Loading-Spinner während Stornierung',
|
||||
'Erfolgsmeldung nach Stornierung',
|
||||
'Fehlermeldung bei Fehler',
|
||||
'Token bleibt nach Stornierung gültig',
|
||||
'Slot wird wieder freigegeben',
|
||||
'Status aktualisiert sich'
|
||||
]);
|
||||
|
||||
// === 10. FEHLERBEHANDLUNG ===
|
||||
addSection(form, '10. Fehlerbehandlung', 'Teste das Fehler-Handling');
|
||||
|
||||
addParagraph(form, '10.1 Ungültige Token');
|
||||
addCheckboxes(form, [
|
||||
'Nicht existierender Token: Fehlermeldung',
|
||||
'Abgelaufener Token: Fehlermeldung',
|
||||
'Leerer Token: Fehlermeldung',
|
||||
'Fehlermeldung benutzerfreundlich auf Deutsch'
|
||||
]);
|
||||
|
||||
addParagraph(form, '10.2 Netzwerkfehler');
|
||||
addCheckboxes(form, [
|
||||
'API nicht erreichbar: Fehlermeldung',
|
||||
'Timeout: Fehlermeldung',
|
||||
'Fehler während Stornierung: Meldung bleibt sichtbar'
|
||||
]);
|
||||
|
||||
// === 11. PERFORMANCE ===
|
||||
addSection(form, '11. Performance & Ladezeiten', 'Teste Performance-Aspekte');
|
||||
addCheckboxes(form, [
|
||||
'Statusseite lädt in < 2 Sekunden',
|
||||
'Keine sichtbaren Layout-Shifts',
|
||||
'Loading-Spinner während Laden',
|
||||
'Bilder optimiert geladen',
|
||||
'Keine JavaScript-Fehler in Console'
|
||||
]);
|
||||
|
||||
// === 12. ACCESSIBILITY & BROWSER ===
|
||||
addSection(form, '12. Accessibility & Browser-Kompatibilität', 'Teste Zugänglichkeit und Browser');
|
||||
|
||||
addParagraph(form, '12.1 Accessibility');
|
||||
addCheckboxes(form, [
|
||||
'Buttons mit Tastatur erreichbar',
|
||||
'Fokus-Indikatoren sichtbar',
|
||||
'Farbkontraste ausreichend (WCAG AA)',
|
||||
'Alt-Texte für Bilder vorhanden'
|
||||
]);
|
||||
|
||||
addParagraph(form, '12.2 Browser-Kompatibilität');
|
||||
addCheckboxes(form, [
|
||||
'Chrome (aktuell): Funktioniert',
|
||||
'Firefox (aktuell): Funktioniert',
|
||||
'Edge (aktuell): Funktioniert',
|
||||
'Mobile Browser: Funktioniert'
|
||||
]);
|
||||
|
||||
addParagraph(form, '12.3 Responsive Design');
|
||||
addCheckboxes(form, [
|
||||
'Desktop (>1024px): Layout korrekt',
|
||||
'Tablet (768-1024px): Layout korrekt',
|
||||
'Mobile (320-767px): Layout korrekt',
|
||||
'Touch-Targets ausreichend groß (≥44x44px)'
|
||||
]);
|
||||
|
||||
// === 13. SICHERHEIT ===
|
||||
addSection(form, '13. Sicherheit', 'Teste Sicherheitsaspekte');
|
||||
|
||||
addParagraph(form, '13.1 Token-Sicherheit');
|
||||
addCheckboxes(form, [
|
||||
'Token ausreichend lang (UUID)',
|
||||
'Token nicht vorhersagbar',
|
||||
'Token läuft nach 30 Tagen ab',
|
||||
'Abgelaufene Token werden abgelehnt'
|
||||
]);
|
||||
|
||||
addParagraph(form, '13.2 Datenschutz');
|
||||
addCheckboxes(form, [
|
||||
'Keine sensiblen Daten in URLs (außer Token)',
|
||||
'Keine Kundendaten in Browser-Console',
|
||||
'E-Mail-Adressen geschützt',
|
||||
'Telefonnummern geschützt'
|
||||
]);
|
||||
|
||||
// === 14. EDGE CASES ===
|
||||
addSection(form, '14. Edge Cases', 'Teste Sonderfälle und Extremwerte');
|
||||
|
||||
addParagraph(form, '14.1 Extremwerte');
|
||||
addCheckboxes(form, [
|
||||
'Sehr lange Behandlungsnamen korrekt dargestellt',
|
||||
'Sehr lange Notizen korrekt dargestellt',
|
||||
'Sehr hohe Preise korrekt formatiert',
|
||||
'Termin > 30 Tage: Token-Ablauf korrekt'
|
||||
]);
|
||||
|
||||
addParagraph(form, '14.2 Sonderfälle');
|
||||
addCheckboxes(form, [
|
||||
'Termin heute 23:59: Frist korrekt',
|
||||
'Sommerzeit/Winterzeit-Wechsel: Korrekt',
|
||||
'Mehrere Buchungen desselben Kunden: Eigene Tokens',
|
||||
'Gleichzeitiger Zugriff: Kein Konflikt'
|
||||
]);
|
||||
|
||||
// === TESTERGEBNISSE ===
|
||||
addSection(form, 'Testergebnisse & Bewertung', 'Dokumentiere deine Testergebnisse');
|
||||
|
||||
form.addTextItem()
|
||||
.setTitle('Getestet von (Name)')
|
||||
.setRequired(true);
|
||||
|
||||
form.addDateItem()
|
||||
.setTitle('Test-Datum')
|
||||
.setRequired(true);
|
||||
|
||||
form.addTextItem()
|
||||
.setTitle('Browser/Gerät (z.B. "Chrome 120 auf Windows 11")');
|
||||
|
||||
form.addParagraphTextItem()
|
||||
.setTitle('Kritische Fehler (Blocker)')
|
||||
.setHelpText('Beschreibe kritische Fehler, die ein Release verhindern würden');
|
||||
|
||||
form.addParagraphTextItem()
|
||||
.setTitle('Mittelschwere Fehler')
|
||||
.setHelpText('Beschreibe Fehler, die behoben werden sollten');
|
||||
|
||||
form.addParagraphTextItem()
|
||||
.setTitle('Kleinere Probleme')
|
||||
.setHelpText('Beschreibe kleinere Verbesserungsvorschläge');
|
||||
|
||||
form.addMultipleChoiceItem()
|
||||
.setTitle('Gesamtbewertung')
|
||||
.setChoiceValues([
|
||||
'✅ Alle Tests bestanden - Release-fähig',
|
||||
'⚠️ Tests bestanden mit kleineren Problemen',
|
||||
'❌ Kritische Fehler gefunden - Nachbesserung erforderlich'
|
||||
])
|
||||
.setRequired(true);
|
||||
|
||||
form.addParagraphTextItem()
|
||||
.setTitle('Zusätzliche Notizen')
|
||||
.setHelpText('Weitere Beobachtungen und Anmerkungen');
|
||||
|
||||
// === FORMULAR ABSCHLUSS ===
|
||||
Logger.log('✅ Formular erfolgreich erstellt!');
|
||||
Logger.log('📋 Titel: ' + form.getTitle());
|
||||
Logger.log('🔗 URL: ' + form.getPublishedUrl());
|
||||
Logger.log('📝 Editor-URL: ' + form.getEditUrl());
|
||||
Logger.log('');
|
||||
Logger.log('👉 Öffne das Formular in deinem Browser:');
|
||||
Logger.log(form.getPublishedUrl());
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
// === HILFSFUNKTIONEN ===
|
||||
|
||||
function addSection(form, title, description) {
|
||||
form.addPageBreakItem()
|
||||
.setTitle(title)
|
||||
.setHelpText(description);
|
||||
}
|
||||
|
||||
function addParagraph(form, text) {
|
||||
form.addSectionHeaderItem()
|
||||
.setTitle(text);
|
||||
}
|
||||
|
||||
function addCheckboxes(form, items) {
|
||||
items.forEach(item => {
|
||||
form.addCheckboxItem()
|
||||
.setTitle(item)
|
||||
.setChoiceValues(['✓'])
|
||||
.showOtherOption(false);
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user