Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save pliablepixels/5f6570bce208b1ea9f18ac69ab9b8e94 to your computer and use it in GitHub Desktop.

Select an option

Save pliablepixels/5f6570bce208b1ea9f18ac69ab9b8e94 to your computer and use it in GitHub Desktop.
Test driven approach
## 👤 User
The full walkthrough tests are surfacial. If I want to write human readable instructions on the flow (I want it to go step by step into each screen and test functionality of items), and use that human redable instructions to generate code for e2e tests, what is the best approach?
---
## 🤖 Claude
Great question! For human-readable test specifications that generate E2E tests, here are the best approaches for your Playwright setup:
## Recommended Approaches
### 1. **BDD with Gherkin + Playwright** (Most Human-Readable)
**Install:**
```bash
npm install -D @cucumber/cucumber @playwright/test playwright-bdd
```
**Write scenarios in `.feature` files:**
```gherkin
# tests/features/monitor-management.feature
Feature: Monitor Management
As a ZoneMinder user
I want to view and manage my monitors
So that I can monitor my security cameras
Scenario: View live monitor feed
Given I am logged into zmNg
And I have at least one monitor configured
When I navigate to the Monitors page
Then I should see a list of all monitors
And each monitor should show its current status
Scenario: Download monitor snapshot
Given I am on the Monitors page
And I can see "Front Door" monitor
When I click on "Front Door" monitor
And I click the "Download Snapshot" button
Then a snapshot image should be downloaded
And the filename should contain "Front_Door"
Scenario: View monitor properties
Given I am viewing the "Front Door" monitor
When I click the "Properties" button
Then I should see the monitor details dialog
And I should see the monitor ID
And I should see the monitor resolution
And I should see the streaming URL
```
**Generate step definitions:**
```typescript
// tests/steps/monitor-steps.ts
import { Given, When, Then } from '@cucumber/cucumber';
import { expect } from '@playwright/test';
Given('I am logged into zmNg', async function() {
await this.page.goto('/');
// Use existing auth setup
});
Given('I have at least one monitor configured', async function() {
// API call or check
});
When('I navigate to the Monitors page', async function() {
await this.page.getByRole('link', { name: 'Monitors' }).click();
await expect(this.page).toHaveURL(/.*monitors/);
});
Then('I should see a list of all monitors', async function() {
await expect(this.page.getByTestId('monitor-grid')).toBeVisible();
});
```
---
### 2. **Markdown Test Plans → Code** (Simpler Alternative)
**Write test plans in markdown:**
```markdown
# tests/test-plans/monitor-workflow.md
## Test: View and Interact with Monitors
### Prerequisites
- User is logged in
- At least 2 monitors configured (Front Door, Backyard)
### Steps
1. **Navigate to Monitors page**
- Click "Monitors" in sidebar
- Verify URL contains "/monitors"
- Verify page title is "Monitors"
2. **Verify monitor list loads**
- Count visible monitor cards
- Expect at least 2 monitors shown
- Verify "Front Door" monitor is visible
- Verify "Backyard" monitor is visible
3. **Check monitor status indicators**
- Verify each monitor shows online/offline status
- Verify each monitor shows stream preview
4. **Download snapshot from monitor**
- Click on "Front Door" monitor card
- Wait for live view to load
- Click "Download Snapshot" button
- Verify download started
- Verify filename matches pattern: `Front_Door_*.jpg`
5. **View monitor properties**
- Click "Properties" icon on "Front Door"
- Wait for properties dialog to open
- Verify monitor ID is displayed
- Verify resolution (e.g., "1920x1080")
- Verify streaming URL contains "/cgi-bin/nph-zms"
- Close properties dialog
### Expected Results
- All monitors load successfully
- Snapshot downloads correctly
- Properties show accurate information
```
**Use AI to convert to tests** (or use a script):
```typescript
// tests/monitors-workflow.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Monitor Workflow', () => {
test.beforeEach(async ({ page }) => {
// Prerequisites
await page.goto('/monitors');
// Assume authenticated via global setup
});
test('View and interact with monitors', async ({ page }) => {
// Step 1: Navigate to Monitors page
await page.getByRole('link', { name: 'Monitors' }).click();
await expect(page).toHaveURL(/.*monitors/);
await expect(page.getByRole('heading', { name: 'Monitors' })).toBeVisible();
// Step 2: Verify monitor list loads
const monitorCards = page.locator('[data-testid="monitor-card"]');
await expect(monitorCards).toHaveCount(2, { timeout: 10000 });
await expect(page.getByText('Front Door')).toBeVisible();
await expect(page.getByText('Backyard')).toBeVisible();
// Step 3: Check monitor status indicators
// ... continue implementation
});
});
```
---
### 3. **Enhanced Comments in Tests** (Minimal Change)
Add detailed comments to existing test structure:
```typescript
// tests/monitor-management.spec.ts
import { test, expect } from '@playwright/test';
test.describe('Monitor Management - Complete Workflow', () => {
/**
* TEST SCENARIO: View Live Monitor Feed
*
* GIVEN: User is logged into zmNg with configured monitors
* WHEN: User navigates to Monitors page
* THEN:
* - Monitor list is displayed
* - Each monitor shows name, status, and preview
* - Live streams are loading
*/
test('should display monitor list with live previews', async ({ page }) => {
// STEP 1: Navigate to Monitors page
await page.goto('/monitors');
// STEP 2: Wait for monitors to load
const monitorGrid = page.locator('[data-testid="monitor-grid"]');
await expect(monitorGrid).toBeVisible({ timeout: 10000 });
// STEP 3: Verify monitor count
const monitors = page.locator('[data-testid="monitor-card"]');
const count = await monitors.count();
expect(count).toBeGreaterThan(0);
// STEP 4: Verify each monitor has required elements
for (let i = 0; i < count; i++) {
const monitor = monitors.nth(i);
await expect(monitor.locator('[data-testid="monitor-name"]')).toBeVisible();
await expect(monitor.locator('[data-testid="monitor-status"]')).toBeVisible();
}
});
});
```
---
## My Recommendation for Your Project
**Use a hybrid approach:**
1. **Create test plans in markdown** (`tests/test-plans/`)
- Easy to review with non-technical stakeholders
- Can be version controlled
- Serves as documentation
2. **Use Playwright's built-in features** with detailed test descriptions:
```typescript
test.describe('Monitor Management', () => {
test('User can view live monitor feed and download snapshot', async ({ page }) => {
await test.step('Navigate to Monitors page', async () => {
await page.getByRole('link', { name: 'Monitors' }).click();
});
await test.step('Verify monitor list loads', async () => {
await expect(page.getByTestId('monitor-grid')).toBeVisible();
});
await test.step('Click on Front Door monitor', async () => {
await page.getByText('Front Door').click();
});
await test.step('Download snapshot', async () => {
const downloadPromise = page.waitForEvent('download');
await page.getByRole('button', { name: 'Download Snapshot' }).click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toMatch(/Front_Door.*\.jpg/);
});
});
});
```
3. **Add test IDs to UI components** for reliable selectors:
```tsx
// In your components
<div data-testid="monitor-card">
<h3 data-testid="monitor-name">{monitor.name}</h3>
<span data-testid="monitor-status">{monitor.status}</span>
</div>
```
**Would you like me to:**
1. Set up BDD/Gherkin with Playwright?
2. Create a markdown test plan template?
3. Show you how to use `test.step()` to make existing tests more readable?
4. Add data-testid attributes to key UI components?
---
## 👤 User
Lets do all of the above but in a new branch
---
## 🤖 Claude
I'll set up a comprehensive E2E testing framework with BDD, test plans, and improved test structure in a new branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment