WellNuo Lite architecture: - Simplified navigation flow with NavigationController - Profile editing with API sync (/auth/profile endpoint) - OTP verification improvements - ESP WiFi provisioning setup (espProvisioning.ts) - E2E testing infrastructure (Playwright) - Speech recognition hooks (web/native) - Backend auth enhancements This is the stable version submitted to App Store. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
159 lines
6.1 KiB
TypeScript
159 lines
6.1 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
const BASE_URL = 'https://wellnuo.smartlaunchhub.com/app/';
|
|
|
|
test.describe('WellNuo Web App Tests', () => {
|
|
|
|
test('Login screen loads correctly', async ({ page }) => {
|
|
page.on('console', msg => console.log(`BROWSER: ${msg.text()}`));
|
|
page.on('pageerror', err => console.log(`ERROR: ${err.message}`));
|
|
|
|
await page.goto(BASE_URL);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Check main elements are visible
|
|
await expect(page.getByText('Welcome to WellNuo')).toBeVisible();
|
|
await expect(page.getByPlaceholder('Enter your email')).toBeVisible();
|
|
await expect(page.getByText('Continue')).toBeVisible();
|
|
await expect(page.getByText('I have an invite code')).toBeVisible();
|
|
|
|
console.log('✅ Login screen loaded correctly');
|
|
});
|
|
|
|
test('Email validation works', async ({ page }) => {
|
|
page.on('console', msg => console.log(`BROWSER: ${msg.text()}`));
|
|
|
|
await page.goto(BASE_URL);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Try invalid email
|
|
await page.getByPlaceholder('Enter your email').fill('invalid-email');
|
|
await page.getByText('Continue').click();
|
|
|
|
// Should show error or stay on same page
|
|
await page.waitForTimeout(1000);
|
|
const url = page.url();
|
|
expect(url).toContain('/app'); // Should not navigate away
|
|
|
|
console.log('✅ Invalid email handled correctly');
|
|
});
|
|
|
|
test('Valid email shows OTP screen', async ({ page }) => {
|
|
page.on('console', msg => console.log(`BROWSER: ${msg.text()}`));
|
|
|
|
await page.goto(BASE_URL);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Enter valid email
|
|
await page.getByPlaceholder('Enter your email').fill('test@example.com');
|
|
await page.getByText('Continue').click();
|
|
|
|
// Should show OTP screen
|
|
await expect(page.getByText(/verification code|Enter.*code/i)).toBeVisible({ timeout: 10000 });
|
|
|
|
console.log('✅ OTP screen appears for valid email');
|
|
});
|
|
|
|
test.skip('Full registration flow with temp email', async ({ page }) => {
|
|
// Debug: Log console messages
|
|
page.on('console', msg => console.log(`BROWSER LOG: ${msg.text()}`));
|
|
page.on('pageerror', err => console.log(`BROWSER ERROR: ${err.message}`));
|
|
|
|
// 1. Generate unique email
|
|
const timestamp = Date.now();
|
|
const email = `test.auto.${timestamp}@test.com`;
|
|
console.log(`Testing registration with: ${email}`);
|
|
|
|
// 2. Navigate to landing
|
|
const targetUrl = 'http://localhost:3000/app/';
|
|
console.log(`Navigating to: ${targetUrl}`);
|
|
await page.goto(targetUrl);
|
|
console.log(`Current URL: ${page.url()}`);
|
|
|
|
// Check we are on a login/welcome screen
|
|
// Note: Adjust selectors based on actual UI. Assuming "Enter Email" input exists.
|
|
// Expo web often manages navigation via history API.
|
|
|
|
// Wait for initial load
|
|
await expect(page.getByPlaceholder('Enter your email')).toBeVisible({ timeout: 10000 });
|
|
|
|
// 3. Enter Email and Request OTP
|
|
await page.getByPlaceholder('Enter your email').fill(email);
|
|
// Find "Continue" or "Code" button.
|
|
// Assuming button text contains "Continue" or similar.
|
|
await page.getByRole('button').filter({ hasText: /Continue|Code/i }).click();
|
|
|
|
// 4. Wait for OTP screen
|
|
await expect(page.getByText('Enter Verification Code')).toBeVisible();
|
|
|
|
// 5. Fetch OTP from DB
|
|
// Retrying a few times as DB insert might have slight delay
|
|
let code = '';
|
|
for (let i = 0; i < 5; i++) {
|
|
await page.waitForTimeout(1000); // Wait 1s
|
|
try {
|
|
code = execSync(`node "${FETCH_OTP_SCRIPT}" "${email}"`).toString().trim();
|
|
if (code && code.length === 6) break;
|
|
} catch (e) {
|
|
console.log('Waiting for OTP...');
|
|
}
|
|
}
|
|
expect(code).toMatch(/^\d{6}$/);
|
|
console.log(`Fetched OTP: ${code}`);
|
|
|
|
// 6. Enter OTP
|
|
// Assuming 6 separate inputs or one text input
|
|
// If one input:
|
|
const otpInput = page.getByPlaceholder('000000');
|
|
if (await otpInput.isVisible()) {
|
|
await otpInput.fill(code);
|
|
} else {
|
|
// Expo OTP input might be tricky (hidden input or separate fields)
|
|
// Let's try typing it
|
|
await page.keyboard.type(code);
|
|
}
|
|
|
|
// Submit OTP
|
|
await page.getByRole('button').filter({ hasText: /Verify|Login/i }).click();
|
|
|
|
// 7. Handle "Enter Name" (Complete Profile)
|
|
// If new user, likely asked for name
|
|
try {
|
|
await expect(page.getByText('What should we call you?')).toBeVisible({ timeout: 5000 });
|
|
await page.getByPlaceholder('Your Name').fill('Automated Tester');
|
|
await page.getByRole('button').filter({ hasText: /Continue/i }).click();
|
|
} catch (e) {
|
|
console.log('Skipped name entry (maybe not required?)');
|
|
}
|
|
|
|
// 8. Verify Dashboard
|
|
await expect(page.getByText('Dashboard')).toBeVisible();
|
|
await expect(page.getByText('Julia')).toBeVisible(); // Verify Voice AI present
|
|
|
|
console.log('Registration successful!');
|
|
});
|
|
|
|
test('Existing User Login Flow', async ({ page }) => {
|
|
// Debug: Log console messages
|
|
page.on('console', msg => console.log(`BROWSER: ${msg.text()}`));
|
|
page.on('pageerror', err => console.log(`ERROR: ${err.message}`));
|
|
|
|
await page.goto('https://wellnuo.smartlaunchhub.com/app/');
|
|
|
|
// Wait for app to load
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Fill email
|
|
await page.getByPlaceholder('Enter your email').fill('test@test.com');
|
|
|
|
// Click Continue button (Expo uses div, not button)
|
|
await page.getByText('Continue').click();
|
|
|
|
// Wait for OTP screen
|
|
await expect(page.getByText(/verification code|Enter.*code/i)).toBeVisible({ timeout: 10000 });
|
|
|
|
console.log('OTP screen visible - login flow working!');
|
|
});
|
|
|
|
});
|