Skip to content
Open
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
3 changes: 3 additions & 0 deletions workspaces/cost-management/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,6 @@ site

# E2E test reports
e2e-test-report/
# Playwright test artifacts
**/test-results/
playwright-results.xml
3 changes: 3 additions & 0 deletions workspaces/cost-management/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
"clean": "backstage-cli repo clean",
"test": "backstage-cli repo test",
"test:all": "backstage-cli repo test --coverage",
"e2e-test": "playwright test",
"e2e-test:live": "playwright test --project=live",
"fix": "backstage-cli repo fix",
"lint": "backstage-cli repo lint --since origin/main",
"lint:all": "backstage-cli repo lint",
Expand Down Expand Up @@ -49,6 +51,7 @@
"@microsoft/api-extractor-model": "^7.29.2",
"@microsoft/tsdoc": "^0.16.0",
"@microsoft/tsdoc-config": "^0.18.0",
"@playwright/test": "1.61.1",
"@types/jest": "^30.0.0",
"@types/jsdom": "^27.0.0",
"@useoptic/optic": "^0.55.0",
Expand Down
201 changes: 201 additions & 0 deletions workspaces/cost-management/packages/app/e2e-tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Resource Optimization Plugin E2E Tests

This directory contains end-to-end tests for the Resource Optimization plugin using Playwright.

## Structure

```
e2e-tests/
├── fixtures/
│ └── optimizationResponses.ts # Mock data for API responses
├── pages/
│ └── ResourceOptimizationPage.ts # Page object for optimization UI
├── utils/
│ ├── devMode.ts # Mock utilities for development mode
│ └── apiUtils.ts # General API testing utilities
├── app.test.ts # Basic app functionality test
├── optimization.test.ts # Comprehensive optimization plugin tests
└── README.md # This file
```

## Mock Utilities

### Development Mode vs Production Mode

The tests automatically detect the environment:

- **Development Mode** (`!process.env.PLAYWRIGHT_URL`): Uses mocks for all API calls
- **Production Mode** (`process.env.PLAYWRIGHT_URL`): Uses real API endpoints

### Using Mock Utilities

```typescript
import {
setupOptimizationMocks,
mockOptimizationsResponse,
} from './utils/devMode';

test.beforeEach(async ({ page }) => {
if (devMode) {
// Setup all mocks at once
await setupOptimizationMocks(page);

// Or setup specific mocks
await mockOptimizationsResponse(page, customOptimizations);
}
});
```

### Available Mock Functions

#### `devMode.ts`

- `setupOptimizationMocks(page)` - Setup all mocks for basic testing
- `mockClustersResponse(page, clusters)` - Mock clusters API
- `mockOptimizationsResponse(page, optimizations, status)` - Mock optimizations API
- `mockEmptyOptimizationsResponse(page)` - Mock empty optimizations
- `mockWorkflowExecutionResponse(page, execution, status)` - Mock workflow execution
- `mockAuthTokenResponse(page, token)` - Mock authentication
- `mockAccessCheckResponse(page, hasAccess)` - Mock access check
- `mockAuthGuestRefreshResponse(page)` - Mock guest token refresh
- `mockPermissionResponse(page, hasPermission)` - Mock permission checks
- `mockCostManagementResponse(page, data)` - Mock cost management API
- `mockEmptyCostManagementResponse(page)` - Mock empty cost management data
- `mockCostManagementErrorResponse(page, status)` - Mock cost management errors

#### `apiUtils.ts`

- `waitUntilApiCallSucceeds(page, urlPart)` - Wait for API success
- `mockApiEndpoint(page, urlPattern, responseData, status)` - Generic API mock
- `mockApiError(page, urlPattern, errorMessage, status)` - Mock API errors
- `verifyApiCallMade(page, urlPattern, method)` - Verify API calls

## Page Objects

### ResourceOptimizationPage

Encapsulates all interactions with the optimization plugin UI:

```typescript
const optimizationPage = new ResourceOptimizationPage(page);

// Navigation
await optimizationPage.navigateToOptimization();

// Cluster selection
await optimizationPage.selectCluster('Production Cluster');

// View optimizations
await optimizationPage.viewOptimizations();

// Apply recommendations
await optimizationPage.applyRecommendation('opt-1');

// Verify states
await optimizationPage.verifyOptimizationDisplayed(optimization);
await optimizationPage.expectEmptyState();
await optimizationPage.expectErrorState();
```

## Test Data

### Mock Data Structure

The `fixtures/optimizationResponses.ts` file contains realistic mock data:

```typescript
export const mockOptimizations = [
{
id: 'opt-1',
clusterId: 'cluster-1',
workloadName: 'frontend-deployment',
resourceType: 'CPU',
currentValue: '2000m',
recommendedValue: '1000m',
savings: { cost: 45.5 },
status: 'pending',
severity: 'medium',
// ... more fields
},
// ... more optimizations
];
```

## Running Tests

### Local Development

```bash
# Run all tests
yarn test:e2e

# Run specific test file
yarn playwright test optimization.test.ts

# Run with UI
yarn test:e2e:ui

# Run in headed mode
yarn test:e2e:headed
```

### CI Environment

Tests automatically run in CI when changes are made to the optimization plugin workspace.

## Environment Variables

For production mode testing, set these environment variables:

```bash
export PLAYWRIGHT_URL=http://localhost:3000
export RHHCC_SA_CLIENT_ID=your-client-id
export RHHCC_SA_CLIENT_SECRET=your-client-secret
```

## Writing New Tests

1. **Use page objects** for UI interactions
2. **Mock API calls** in development mode
3. **Test both success and error scenarios**
4. **Validate accessibility** with proper ARIA labels
5. **Use descriptive test names** that explain the user journey

### Example Test Structure

```typescript
test('should handle optimization workflow', async ({ page }) => {
// Setup
if (devMode) {
await mockOptimizationsResponse(page, testOptimizations);
await mockWorkflowExecutionResponse(page, successExecution);
}

// Action
await optimizationPage.navigateToOptimization();
await optimizationPage.selectCluster('test-cluster');
await optimizationPage.viewOptimizations();
await optimizationPage.applyRecommendation('opt-1');

// Verification
await optimizationPage.expectWorkflowSuccess();
});
```

## Configuration

The plugin requires these configurations in `app-config.yaml`:

```yaml
proxy:
endpoints:
'/cost-management/v1':
target: https://console.redhat.com/api/cost-management/v1
allowedHeaders: ['Authorization']
credentials: dangerously-allow-unauthenticated

resourceOptimization:
clientId: ${RHHCC_SA_CLIENT_ID}
clientSecret: ${RHHCC_SA_CLIENT_SECRET}
optimizationWorkflowId: 'patch-k8s-resource'
```
Loading
Loading