✨ feat: add new contact form, hero, features, and richtext blocks; implement scroll-reveal action and update styles
- Introduced ContactFormBlock, FeaturesBlock, HeroBlock, and RichtextBlock components. - Implemented a scroll-reveal action for animations on element visibility. - Enhanced CSS styles for better theming and prose formatting. - Added localization support for new components and updated existing translations. - Created e2e tests for demo pages including contact form validation and navigation. - Added a video tour showcasing the demo pages and interactions.
This commit is contained in:
166
video-tours/tours/demo-showcase.tour.ts
Normal file
166
video-tours/tours/demo-showcase.tour.ts
Normal file
@@ -0,0 +1,166 @@
|
||||
import { tour } from "./fixtures"
|
||||
import { moveThenClick, moveThenType, smoothScroll } from "../helpers"
|
||||
|
||||
/**
|
||||
* Video tour: Full demo showcase
|
||||
*
|
||||
* Walks through all demo pages, demonstrating:
|
||||
* 1. Homepage — hero, features, richtext, FAQ accordion
|
||||
* 2. About page — content blocks
|
||||
* 3. Contact page — form interaction
|
||||
* 4. Language switching (EN ↔ DE with route translation)
|
||||
* 5. 404 page
|
||||
*
|
||||
* Run: yarn tour
|
||||
*/
|
||||
tour("Demo Showcase", async ({ tourPage: page }) => {
|
||||
tour.setTimeout(120000)
|
||||
|
||||
// ── 1. Homepage (German) ─────────────────────────────────────────
|
||||
await page.goto("/de/")
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Scroll down through hero → features
|
||||
await smoothScroll(page, 500)
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Scroll through features
|
||||
await smoothScroll(page, 1200)
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Scroll to richtext/workflow section
|
||||
await smoothScroll(page, 2000)
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Scroll to FAQ accordion
|
||||
await smoothScroll(page, 2800)
|
||||
await page.waitForTimeout(2000)
|
||||
|
||||
// Interact with accordion — click second item
|
||||
const accordionButtons = page.locator("[data-block='accordion'] button")
|
||||
const secondAccordion = accordionButtons.nth(1)
|
||||
if (await secondAccordion.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, secondAccordion)
|
||||
await page.waitForTimeout(1500)
|
||||
}
|
||||
|
||||
// Click third item
|
||||
const thirdAccordion = accordionButtons.nth(2)
|
||||
if (await thirdAccordion.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, thirdAccordion)
|
||||
await page.waitForTimeout(1500)
|
||||
}
|
||||
|
||||
// Scroll to footer
|
||||
await smoothScroll(page, 9999)
|
||||
await page.waitForTimeout(1500)
|
||||
|
||||
// Scroll back to top
|
||||
await smoothScroll(page, 0)
|
||||
await page.waitForTimeout(1500)
|
||||
|
||||
// ── 2. Navigate to About ─────────────────────────────────────────
|
||||
const aboutLink = page.locator('header nav a[href*="ueber-uns"], header nav a[href*="about"]').first()
|
||||
if (await aboutLink.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, aboutLink)
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Slow scroll through about content
|
||||
await smoothScroll(page, 400)
|
||||
await page.waitForTimeout(2000)
|
||||
await smoothScroll(page, 900)
|
||||
await page.waitForTimeout(2000)
|
||||
await smoothScroll(page, 1500)
|
||||
await page.waitForTimeout(1500)
|
||||
}
|
||||
|
||||
// ── 3. Navigate to Contact ───────────────────────────────────────
|
||||
const contactLink = page.locator('header nav a[href*="kontakt"], header nav a[href*="contact"]').first()
|
||||
if (await contactLink.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, contactLink)
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Scroll to form
|
||||
await smoothScroll(page, 500)
|
||||
await page.waitForTimeout(1500)
|
||||
|
||||
// Fill out the contact form
|
||||
const nameInput = page.getByLabel("Name", { exact: false })
|
||||
if (await nameInput.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenType(page, nameInput, "Max Mustermann", { delay: 60 })
|
||||
await page.waitForTimeout(800)
|
||||
}
|
||||
|
||||
const emailInput = page.getByLabel("E-Mail", { exact: false }).or(page.getByLabel("Email", { exact: false }))
|
||||
if (
|
||||
await emailInput
|
||||
.first()
|
||||
.isVisible({ timeout: 2000 })
|
||||
.catch(() => false)
|
||||
) {
|
||||
await moveThenType(page, emailInput.first(), "max@example.com", { delay: 60 })
|
||||
await page.waitForTimeout(800)
|
||||
}
|
||||
|
||||
// Select subject
|
||||
const selectTrigger = page.locator("select, [role='combobox']").first()
|
||||
if (await selectTrigger.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, selectTrigger)
|
||||
await page.waitForTimeout(500)
|
||||
await page.selectOption("select", { index: 2 })
|
||||
await page.waitForTimeout(800)
|
||||
}
|
||||
|
||||
const messageInput = page
|
||||
.getByLabel("Nachricht", { exact: false })
|
||||
.or(page.getByLabel("Message", { exact: false }))
|
||||
if (
|
||||
await messageInput
|
||||
.first()
|
||||
.isVisible({ timeout: 2000 })
|
||||
.catch(() => false)
|
||||
) {
|
||||
await moveThenType(page, messageInput.first(), "Das ist eine Testnachricht für die Video-Tour.", {
|
||||
delay: 40,
|
||||
})
|
||||
await page.waitForTimeout(1000)
|
||||
}
|
||||
|
||||
// Submit form
|
||||
const submitBtn = page
|
||||
.locator("button[type='submit'], button:has-text('Senden'), button:has-text('Send')")
|
||||
.first()
|
||||
if (await submitBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, submitBtn)
|
||||
await page.waitForTimeout(3000) // Wait for toast + simulated API call
|
||||
}
|
||||
}
|
||||
|
||||
// ── 4. Language switch ───────────────────────────────────────────
|
||||
// Switch to English
|
||||
const enLink = page.locator('header a[href*="/en"]').first()
|
||||
if (await enLink.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, enLink)
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Scroll a bit on English page
|
||||
await smoothScroll(page, 300)
|
||||
await page.waitForTimeout(1500)
|
||||
await smoothScroll(page, 0)
|
||||
await page.waitForTimeout(1000)
|
||||
}
|
||||
|
||||
// ── 5. 404 page ─────────────────────────────────────────────────
|
||||
await page.goto("/en/this-page-does-not-exist")
|
||||
await page.waitForTimeout(2500)
|
||||
|
||||
// Click Back to Home
|
||||
const backHomeLink = page.getByRole("link", { name: /back to home/i })
|
||||
if (await backHomeLink.isVisible({ timeout: 2000 }).catch(() => false)) {
|
||||
await moveThenClick(page, backHomeLink)
|
||||
await page.waitForTimeout(2500)
|
||||
}
|
||||
|
||||
// Final pause on homepage
|
||||
await page.waitForTimeout(2000)
|
||||
})
|
||||
Reference in New Issue
Block a user