Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 152 additions & 33 deletions tests/PATTERNFLY_COMMANDS_EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# PatternFly Cypress Commands - Usage Examples

This file demonstrates how to properly use the PatternFly-aware Cypress commands to avoid React state management issues.
This file provides comprehensive examples of PatternFly-aware Cypress commands for distributed tracing UI testing, focusing on semantic selectors and efficient testing patterns.

## ✅ Recommended Usage Patterns

Expand Down Expand Up @@ -61,50 +61,169 @@ cy.byLabelText('Namespace').select('default');
cy.pfButton('Submit').click();
```

## ⚠️ Patterns to Avoid
## 🆕 New Distributed Tracing UI Commands

### 1. Complex Chained Operations
### Menu & Dropdown Interactions

```typescript
// ❌ AVOID: Too many chained operations without waits
cy.pfToolbarItem(0).within(() => {
cy.pfMenuToggle().click();
}).then(() => {
cy.pfMenuItem('Item').click();
}).then(() => {
cy.pfToolbarItem(1).within(() => {
cy.pfMenuToggle().click();
// Tempo instance selection
cy.pfTypeahead('Select a Tempo instance').click();
cy.pfSelectMenuItem('chainsaw-rbac / simplst').click();

// Service filtering with checkboxes
cy.pfMenuToggleByLabel('Multi typeahead checkbox').click();
cy.pfCheckMenuItem('http-rbac-1');
cy.pfCheckMenuItem('http-rbac-2', true); // Explicitly check
cy.pfCheckMenuItem('grpc-rbac-1', false); // Uncheck

// Time range selection
cy.pfMenuToggle('Last 30 minutes').click();
cy.pfSelectMenuItem('Last 1 hour').click();
```

### Navigation Commands

```typescript
// Breadcrumb navigation
cy.pfBreadcrumb('Traces').click();
cy.pfBreadcrumb('Observability').should('be.visible');

// Close buttons (chip groups, modals, etc.)
cy.pfCloseButton('Close chip group').click(); // PatternFly 5
cy.pfCloseButton('Close label group').click(); // PatternFly 6
cy.pfCloseButton().click(); // First close button found (any version)
```

### Trace & Span Interactions

```typescript
// Click on traces
cy.muiFirstTraceLink().click(); // First trace in list
cy.muiTraceLink('http-rbac-2').click(); // Specific service trace

// Interact with span bars
cy.muiFirstSpanBar().click(); // First span bar
cy.muiSpanBar('http-rbac-2').click(); // Specific service span
cy.findByTestId('span-duration-bar').first().click(); // By test ID (multiple spans)
```

### Trace Attribute Validation

```typescript
// Single attribute validation
cy.muiTraceAttribute('net.peer.ip', '1.2.3.4');
cy.muiTraceAttribute('peer.service', 'telemetrygen-client');
cy.muiTraceAttribute('k8s.container.name', 'telemetrygen', true); // Optional attribute

// Custom validation with function
cy.muiTraceAttribute('service.name', (text) => {
return ['http-rbac-1', 'http-rbac-2', 'grpc-rbac-1', 'grpc-rbac-2'].includes(text);
}, false, 'TempoStack'); // Required attribute with logging

// Bulk attribute validation (recommended for multiple attributes)
cy.muiTraceAttributes({
'net.peer.ip': { value: '1.2.3.4' },
'peer.service': { value: 'telemetrygen-client' },
'k8s.container.name': {
value: 'telemetrygen',
optional: true
},
'k8s.namespace.name': {
value: (text) => text.startsWith('chainsaw-'),
optional: true
},
'service.name': {
value: ['http-rbac-1', 'http-rbac-2', 'grpc-rbac-1', 'grpc-rbac-2']
}
}, 'Debug'); // Log prefix for debugging
```

### Complete Workflow Examples

```typescript
// Complete trace inspection workflow
describe('Trace inspection', () => {
it('should navigate and validate trace details', () => {
// Navigate to traces page
cy.visit('/observe/traces');

// Select Tempo instance
cy.pfTypeahead('Select a Tempo instance').click();
cy.pfSelectMenuItem('chainsaw-rbac / simplst').click();

// Set time range
cy.pfMenuToggle('Last 30 minutes').click();
cy.pfSelectMenuItem('Last 1 hour').click();

// Filter by services
cy.pfMenuToggleByLabel('Multi typeahead checkbox').click();
cy.pfCheckMenuItem('http-rbac-1');
cy.pfCheckMenuItem('http-rbac-2');

// Click first trace
cy.muiFirstTraceLink().click();

// Click on span for details
cy.muiFirstSpanBar().click();

// Validate trace attributes efficiently
cy.muiTraceAttributes({
'net.peer.ip': { value: '1.2.3.4' },
'peer.service': { value: 'telemetrygen-client' },
'service.name': {
value: (text) => text.includes('rbac')
}
});

// Navigate back
cy.pfBreadcrumb('Traces').click();
});
});
```

// ✅ BETTER: Break into separate operations with waits
cy.pfToolbarItem(0).within(() => {
cy.get('.pf-v6-c-menu-toggle').first().click();
});
cy.get('.pf-v6-c-menu__item').contains('Item').click();
cy.wait(1000); // Allow React state to stabilize
cy.pfToolbarItem(1).within(() => {
cy.get('.pf-v6-c-menu-toggle').first().click();
});
## 🔄 PatternFly 5 & 6 Compatibility

Our commands seamlessly support both PatternFly 5 and PatternFly 6 components:

### Close Buttons

```typescript
// PatternFly 5 - Chip Group
// <button aria-label="Close chip group" class="pf-v5-c-button pf-m-plain">
cy.pfCloseButton('Close chip group').click();

// PatternFly 6 - Label Group
// <button aria-label="Close label group" class="pf-v6-c-button pf-m-plain pf-m-no-padding">
cy.pfCloseButton('Close label group').click();

// Works with both versions automatically
cy.pfCloseButton('Close').click(); // Finds any close button
```

### Menu Components

```typescript
// Both PF5 and PF6 menu structures supported
cy.pfMenuToggle('Select Instance').click(); // Works with .pf-v5-c-menu-toggle or .pf-v6-c-menu-toggle
cy.pfSelectMenuItem('tempo-stack').click(); // Works with .pf-v5-c-menu__item or .pf-v6-c-menu__item
cy.pfCheckMenuItem('service-name'); // Handles both PF5/PF6 checkbox patterns
```

### 2. Rapid Sequential Clicks
### Button Components

```typescript
// ❌ AVOID: Multiple rapid interactions
cy.pfMenuToggle().click();
cy.pfMenuItem('Item1').click();
cy.pfMenuToggle().click(); // Too fast, React state not updated
cy.pfMenuItem('Item2').click();

// ✅ BETTER: Add stabilization waits
cy.pfMenuToggle().click();
cy.pfMenuItem('Item1').click();
cy.wait(500); // Let React update
cy.pfMenuToggle().click();
cy.pfMenuItem('Item2').click();
// PatternFly button targeting (version-agnostic)
cy.pfButton('Create Instance').click(); // Targets .pf-v5-c-button or .pf-v6-c-button
cy.pfEmptyState().should('be.visible'); // Works with both .pf-v5-c-empty-state and .pf-v6-c-empty-state
```

### Key Benefits

- ✅ **Automatic detection** - Commands work with both PF5 and PF6 automatically
- ✅ **Future-proof** - Ready for PatternFly version upgrades
- ✅ **Consistent API** - Same command syntax across versions
- ✅ **Robust selectors** - Uses semantic attributes over version-specific classes

## 🛡️ Defensive Programming Patterns

### 1. Check Element Existence
Expand Down
69 changes: 69 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,73 @@ We can either open Cypress GUI(open) or run Cypress in headless mode(run) to run
```bash
npx cypress open
npx cypress run

# Run specific test files
npx cypress run --spec "e2e/dt-plugin-tests.cy.ts"

# Skip debug files during CI runs
npx cypress run --ignore-pattern "**/*debug*.cy.ts"
```

## Test Architecture & Best Practices

### Custom Commands
This project includes a comprehensive set of custom Cypress commands optimized for PatternFly and Material-UI components. These commands provide:

- **Semantic selectors** instead of brittle CSS selectors
- **Component-aware interactions** for PatternFly elements
- **Bulk validation** for trace attributes (75% code reduction)
- **Debug-friendly** commands with built-in logging

### Key Command Categories

#### PatternFly Components
```typescript
// Menu interactions
cy.pfMenuToggle('Select Instance').click()
cy.pfSelectMenuItem('tempo-stack').click()
cy.pfCheckMenuItem('service-name')

// Navigation
cy.pfBreadcrumb('Traces').click()
cy.pfButton('Create').click()
cy.pfCloseButton('Close dialog').click()

// Form controls
cy.pfTypeahead('Select a Tempo instance').click()
cy.pfMenuToggleByLabel('Multi typeahead').click()
```

#### Trace & Observability
```typescript
// Trace interactions
cy.muiFirstTraceLink().click()
cy.muiTraceLink('http-service').click()
cy.muiSpanBar('grpc-service').click()

// Attribute validation (bulk)
cy.muiTraceAttributes({
'service.name': { value: 'my-service' },
'net.peer.ip': { value: '1.2.3.4' },
'k8s.namespace': { value: 'test-ns', optional: true }
})
```

### Debug Testing
A debug test file (`dt-plugin-tests-debug.cy.ts.skip`) is available for rapid iteration without setup/teardown overhead. To use:

```bash
# Enable debug test
mv tests/e2e/dt-plugin-tests-debug.cy.ts.skip tests/e2e/dt-plugin-tests-debug.cy.ts

# Run debug test only
npx cypress run --spec "e2e/dt-plugin-tests-debug.cy.ts"

# Disable debug test
mv tests/e2e/dt-plugin-tests-debug.cy.ts tests/e2e/dt-plugin-tests-debug.cy.ts.skip
```

### Documentation
- **SELECTOR_BEST_PRACTICES.md** - Comprehensive selector guidelines and command usage
- **PATTERNFLY_COMMANDS_EXAMPLES.md** - Complete command examples and workflows
- **README.md** - This file with setup and architecture overview
Loading