# Master Playwright Test Script Review Hints

## Overview
This is the master hints file that combines all critical patterns and best practices from the Halo QA automation test suite. Use this when reviewing any Playwright test script in the project.

## Related Hint Files
- **regression-test-hints.md** - Regression test patterns for systematic testing
- **hayley-navigation-hints.md** - Hayley-specific navigation patterns
- **dashboard-widget-hints.md** - Dashboard and widget test patterns (UPDATED with dashboard operations)
- **export-test-hints.md** - Export functionality rules
- **table-explorer-hints.md** - Table Explorer comprehensive guide (UPDATED 2025-09-04 with dynamic column detection)
- **table-explorer-csv-hints.md** - Table Explorer CSV export specific patterns

## Universal Requirements (ALL Tests Must Have)

### 1. Test Timeout Configuration
```typescript
// MANDATORY at the beginning of EVERY test file
test.setTimeout(10 * 60 * 1000); // 10 minutes for slow builds
```

### 2. Test Step Organization
```typescript
// ALL test actions must be wrapped in test.step()
await test.step('Step Description', async () => {
  // Implementation
});
```

### 3. No NetworkIdle Wait
```typescript
// NEVER use this - causes browser closure
❌ await page.waitForLoadState('networkidle');

// Use this instead
✅ await page.waitForTimeout(2000); // 2-5 seconds
```

## Page Object Model (Required)

### Standard Imports
```typescript
import { test, expect } from '@playwright/test';
import { LoginPage } from '../pages/login.page';
import { DashboardMainPage } from '../pages/dashboard-main.page';
import { WidgetsPage } from '../pages/widgets.page';
import { DashboardExportPage } from '../pages/dashboard-export.page'; // If needed
```

### Page Object Initialization
```typescript
const loginPage = new LoginPage(page);
const dashboardPage = new DashboardMainPage(page);
const widgetsPage = new WidgetsPage(page);
const exportPage = new DashboardExportPage(page); // If needed
```

## Authentication Rules

### Login Flow (CRITICAL)
```typescript
// ALWAYS login through Halo QA first
await loginPage.goto(); // Goes to https://halo-qa.hyly.ai
await loginPage.login(email, password);

// NEVER navigate directly to other apps for login
❌ await page.goto('https://hayley.hyly.ai/login');
```

### Valid Credentials
- **Current**: `cdp@hy.ly` / `BMy2L1rRXZlkKoTU7`
- **Legacy**: `cdp@hy.ly` / `rnJi75ESFutATsbDN` (still acceptable)

### Credential Patterns (All Acceptable)
```typescript
// Option 1: Environment variables with fallback
process.env.TEST_EMAIL || 'cdp@hy.ly'

// Option 2: Dotenv
import * as dotenv from 'dotenv';
dotenv.config();
process.env.TEST_EMAIL!

// Option 3: Hardcoded (if consistent)
'cdp@hy.ly'
```

## Navigation Patterns

### Dashboard Navigation
```typescript
// Use page object methods
await dashboardPage.navigateToDashboards();
await dashboardPage.clickNewDashboard();

// Generate unique names
const uniqueDashboardName = await dashboardPage.generateUniqueDashboardName('Prefix');
```

### Multi-App Navigation
```typescript
// Step 1: Login to Halo QA
await loginPage.goto();
await loginPage.login(credentials);

// Step 2: Navigate to other apps
await page.goto('https://hayley.hyly.ai/home');
await page.waitForTimeout(3000);
```

## Selector Strategy (Priority Order)

1. **Page Object Methods** (BEST)
   ```typescript
   await dashboardPage.navigateToDashboards();
   ```

2. **Semantic Selectors**
   ```typescript
   page.getByRole('button', { name: 'text' })
   page.getByText('text', { exact: true })
   page.getByLabel('label')
   ```

3. **Data Attributes**
   ```typescript
   page.locator('[data-testid="element-id"]')
   ```

4. **Class Selectors** (with fallbacks)
   ```typescript
   page.locator('.dashboard-card, .widget-container, [data-testid*="card"]')
   ```

## Widget Handling

### Widget Selection Flow
```typescript
await widgetsPage.clickSeeAllWidgets();
await widgetsPage.selectTouredConversions(); // Or other widget
await widgetsPage.addFirstCard(); // Or addAllDistinctCards()
```

### Known Widget Cards
- **Toured Conversions**: 5 distinct cards
- **First Touch Attribution**: 5 distinct cards
- **SmartDA**: Multiple variations with dropdowns

## Export Functionality

### PDF Export Pattern
```typescript
// Export via Share button (top right)
const exportSuccess = await exportPage.exportDashboardAsPdf();
expect(exportSuccess).toBeTruthy();
```

**Important**: Only PDF export is available (not Excel, PowerPoint, or Image)

## Assertions and Verification

### Required Verifications
```typescript
// Login verification
const isOnDashboard = await dashboardPage.verifyOnDashboardPage();
expect(isOnDashboard).toBeTruthy();

// URL verification
expect(page.url()).toContain('halo-qa.hyly.ai');

// Element visibility
await expect(element).toBeVisible({ timeout: 5000 });

// Count verification with error message (MANDATORY for Table Explorer)
expect(rowCount, `❌ TABLE DATA FAILED: No data rows found. Expected at least 1 row, got ${rowCount}`).toBeGreaterThan(0);
expect(cardCount, `❌ CARD COUNT FAILED: Expected at least ${expectedCount} cards, got ${cardCount}`).toBeGreaterThanOrEqual(expectedCount);
```

### Strict Assertions (MANDATORY for Table Explorer Tests)
```typescript
// ALL assertions MUST include descriptive error messages
✅ expect(value, `❌ ERROR_TYPE: Description. Expected X, Got ${value}`).toBeGreaterThan(0);

// Error message format: ❌ [ERROR_TYPE]: [Description]. Expected [X], Got [Y]
✅ expect(filename, `❌ FILENAME VALIDATION FAILED: Downloaded file "${filename}" does not contain expected text`).toContain('Property Breakdown');
✅ expect(firstRowBackToFirst?.trim(), `❌ FIRST BUTTON FAILED: Expected "${firstRowBefore?.trim()}", got "${firstRowBackToFirst?.trim()}"`).toBe(firstRowBefore?.trim());

❌ expect(rowCount).toBeGreaterThan(0); // Missing error message
```

### Avoid Meaningless Assertions
```typescript
❌ expect(true).toBeTruthy();
✅ expect(actualValue).toBe(expectedValue);
✅ expect(actualValue, `❌ Failed: Expected ${expectedValue}, got ${actualValue}`).toBe(expectedValue);
```

## Wait Strategies

### Acceptable Waits
```typescript
await page.waitForTimeout(2000); // 2-5 seconds for stability
await element.waitFor({ state: 'visible', timeout: 30000 });
await page.waitForURL('**/path');
```

### Never Use
```typescript
await page.waitForLoadState('networkidle'); // Causes browser issues
```

## File Structure Requirements

### Import Paths
- Same level: `'../pages/login.page'`
- Subfolder tests: `'../../pages/login.page'`

### Test Naming
```typescript
test('Clear test description - Test ID: XXX-###', async ({ page }) => {
  // Implementation
});
```

## Console Logging (Acceptable)
```typescript
console.log(`✅ Test completed successfully - ${details}`);
console.log(`Current URL: ${page.url()}`);
```

## Common Patterns to Accept

1. **Multiple Selector Fallbacks**
   - Try-catch blocks with different selectors
   - OR operators in selectors
   - Conditional navigation based on UI state

2. **Environment Variations**
   - Different credential handling approaches
   - Various timeout values (within reason)
   - Optional dotenv usage

3. **Dashboard Counter System**
   - Uses `utils/dashboard-counter.txt`
   - Ensures unique naming across test runs

## Red Flags - Automatic Rejection

1. **Missing test.setTimeout()**
2. **Using waitForLoadState('networkidle')**
3. **Direct login to non-Halo apps**
4. **No test.step() organization**
5. **Meaningless assertions (expect(true))**
6. **Assertions without error messages** (NEW - CRITICAL for Table Explorer tests)
7. **Hardcoded column names in Table Explorer tests** (NEW - MUST use dynamic detection)
8. **Wrong import paths**
9. **Not using page objects when available**
10. **Hardcoded credentials without any flexibility**
11. **Missing login verification**
12. **Testing unsupported features (Excel export, etc.)**

## Special Test Types

### Regression Tests (NEW)
- Use REG-XXX naming convention
- Extended timeouts (40s initial, 10s after operations)
- Comprehensive test steps with final summary
- Debug logging for troubleshooting
- Loop patterns for multiple operations
- Graceful error handling with fallbacks

### Dashboard Operations (NEW)
- **Delete**: Use three dots menu → Delete (exact match) → Confirm
- **Duplicate**: Creates dashboard with " (1)" suffix
- **Favorites**: Use data-testid="favourite-button" → Add button → Navigate to Favorites
- Check My Dashboards visibility before New Dashboard
- Wait 10s after major operations for build reload

### Table Explorer Tests (NEW - UPDATED 2025-09-04)
- **CRITICAL**: ALWAYS use dynamic column detection (NEVER hardcode column names)
- **CRITICAL**: ALL assertions MUST have descriptive error messages
- Multiple selector approaches for opening Table Explorer (button → radio → text)
- Extended wait times: 40s initial load, 30s before Table Explorer, 3s after dialog actions
- Dynamic sorting/filtering on ANY data column
- Pagination testing with all 4 buttons (<<, <, >, >>)
- Property selection with checkbox toggles
- CSV export validation with file size and content checks
- Pattern: Primary column = first non-filter column, Data columns = all other non-filter columns
- Filter columns: Any column containing '>=' or starting with '>'

```typescript
// Dynamic column detection (MANDATORY)
const primaryColumn = columnNames.find(h =>
  h && h.trim() !== '' && !h.includes('>=') && !h.startsWith('>')
) || '';

const dataColumns = columnNames.filter(h =>
  h && h !== primaryColumn && !h.includes('>=') && !h.startsWith('>') && h.trim() !== ''
);

// Strict assertion with error message (MANDATORY)
expect(rowCount, `❌ TABLE DATA FAILED: No data rows found. Expected at least 1 row, got ${rowCount}`).toBeGreaterThan(0);
```

### Hayley Navigation Tests
- Must login through Halo QA first
- Can use direct URL navigation after login
- Accept flexible URL patterns for Hayley

### Widget Tests
- Must handle widget panel open/close
- Should verify card addition
- Use appropriate widget-specific methods

### Export Tests
- Only test PDF export
- Access via Share button
- Must add content before export

## Review Priorities

1. **Functionality**: Will the test actually work?
2. **Reliability**: Will it handle UI variations?
3. **Maintainability**: Uses page objects and good patterns?
4. **Clarity**: Clear test steps and assertions?
5. **Best Practices**: Follows established patterns?

## Final Notes

- Be pragmatic about minor variations
- Focus on critical issues that would cause failures
- Accept different valid approaches to the same problem
- Consider the test's purpose and context
- Prioritize working tests over perfect tests