# Welcome Tour Template Tests step-by-step onboarding tour, skip, and completion behaviour. ## Prerequisites - Newly registered session (first login) via `{{newUserStorageStatePath}}` - Tour has `{{tourStepCount}}` steps - App running at `{{baseUrl}}` --- ## TypeScript ```typescript import { test, expect } from '@playwright/test'; test.describe('Welcome Tour', () => { test.use({ storageState: '{{newUserStorageStatePath}}' }); // Happy path: tour shown on first login test('shows welcome tour on first login', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeVisible(); await expect(page.getByText(/step 1 of {{tourStepCount}}/i)).toBeVisible(); }); // Happy path: advance through all steps test('advances through all tour steps', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); for (let i = 1; i <= {{tourStepCount}}; i++) { await expect(page.getByText(new RegExp(`step ${i} of {{tourStepCount}}`, 'i'))).toBeVisible(); if (i < {{tourStepCount}}) { await page.getByRole('button', { name: /next/i }).click(); } else { await page.getByRole('button', { name: /finish|done|get started/i }).click(); } } await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeHidden(); }); // Happy path: back navigation within tour test('navigates back to previous step', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await page.getByRole('button', { name: /next/i }).click(); await expect(page.getByText(/step 2 of {{tourStepCount}}/i)).toBeVisible(); await page.getByRole('button', { name: /back|previous/i }).click(); await expect(page.getByText(/step 1 of {{tourStepCount}}/i)).toBeVisible(); }); // Happy path: skip tour test('skips tour and dismisses overlay', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await page.getByRole('button', { name: /skip.*tour|skip/i }).click(); await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeHidden(); await expect(page.getByRole('heading', { name: /dashboard/i })).toBeVisible(); }); // Happy path: tour not shown on subsequent logins test('tour not shown on second login', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); // Complete or skip tour await page.getByRole('button', { name: /skip.*tour|skip/i }).click(); // Simulate re-login by reloading await page.reload(); await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeHidden(); }); // Happy path: tooltip highlights correct element test('tour tooltip highlights the correct UI element', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); const tooltip = page.getByRole('tooltip').or(page.getByRole('dialog', { name: /tour/i })); await expect(tooltip).toBeVisible(); const targetEl = page.getByRole('{{tourStep1TargetRole}}', { name: /{{tourStep1TargetName}}/i }); await expect(targetEl).toBeVisible(); }); // Edge case: close button (×) dismisses tour test('× button dismisses tour', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await page.getByRole('dialog', { name: /welcome|tour/i }) .getByRole('button', { name: /close|×/i }).click(); await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeHidden(); }); }); ``` --- ## JavaScript ```javascript const { test, expect } = require('@playwright/test'); test.describe('Welcome Tour', () => { test.use({ storageState: '{{newUserStorageStatePath}}' }); test('shows welcome tour on first login', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await expect(page.getByRole('dialog', { name: /welcome|tour/i })).toBeVisible(); }); test('skips tour on button click', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); await page.getByRole('button', { name: /skip/i }).click(); await expect(page.getByRole('dialog', { name: /tour/i })).toBeHidden(); }); test('advances through all steps to completion', async ({ page }) => { await page.goto('{{baseUrl}}/dashboard'); for (let i = 1; i < {{tourStepCount}}; i++) { await page.getByRole('button', { name: /next/i }).click(); } await page.getByRole('button', { name: /finish|done|get started/i }).click(); await expect(page.getByRole('dialog', { name: /tour/i })).toBeHidden(); }); }); ``` ## Variants | Variant | Description | |---------|-------------| | Tour on first login | Dialog shown with step 1 of N | | Full completion | All steps advanced → tour dismissed | | Back navigation | Previous step accessible | | Skip tour | Dismissed immediately | | Not shown again | Tour absent on subsequent visits | | Tooltip target | Tour highlights correct element | | Close button | × closes tour |