casewright
v0.0.1
Published
Generate interactive HTML test documentation right from your Playwright test automation solution
Maintainers
Readme
Casewright
Generate interactive HTML test documentation right from your Playwright test automation solution. Transform code-level test cases into human-readable documentation.
Installation
npm install casewrightQuick Start
Add Casewright as a reporter in your playwright.config.ts:
// playwright.config.ts
import { defineConfig } from '@playwright/test'
export default defineConfig({
reporter: [['html'], ['casewright']],
})Run your tests and documentation will be generated automatically:
npx playwright testOpen ./casewright/documentation.html to view your test documentation.
Configuration
Create a configuration file for more control:
npx casewright initThis creates casewright.config.ts:
// casewright.config.ts
import type { CasewrightConfig } from 'casewright'
const config: Partial<CasewrightConfig> = {
places: {
// Patterns to identify Page Object Models
patterns: [/Page$/, /Component$/, /View$/],
mappings: {
LoginPage: 'Login Screen',
},
},
elements: {
mappings: {
submitBtn: 'Submit Button',
},
},
actions: {
// Method name → template. Use {target} for the element, {0}, {1} for arguments.
mappings: {
click: 'Tap {target}',
fill: 'Input {0} into {target}',
},
},
output: {
dir: './casewright',
filename: 'documentation.html',
},
title: 'Test Documentation',
}
export default configGetting maximum value from Casewright
Casewright is an opinionated reporter. To bring the maximum possible value and to correctly convert your Playwright solution into test documentation, it expects (he-he 🥸) that you:
- Use folders inside your tests folder as global categories, for example,
tests/admin,tests/seller,tests/buyeretc. - Use
test.describeas test suites,testas, well, tests, andtest.stepas test steps. Casewright ignores files as it's usually a strictly technical aspect of solution, not a semantical one. - Try to avoid code outside of
test.step. Lines outside of steps will still be parsed and added to documentation but it's gonna to feel weird to have steps along with orphaned lines. - Separate semantically important actions from assertions and do not mix them within one custom function. If your POM functions signs in and expects to be signed in at the same time, you are doing something wrong. If some actions or assertions are not that important or are strictly technical, it's okay to hide them in this way.
- Thoroughly think about your naming convention and try to remain as declarative as you can.
- Use transparently named variable instead of literal for every semantically important value:
// ❌ NO
dashboardPage.searchBar.fill('Test user')
// ✅ YES
const searchedUserName = testData.dashboard.searchedUser.name
dashboardPage.searchBar.fill(searchedUserName)- Remember that Casewright is still a custom reporter, so it can be called conditionally. The most easy way is to introduce an environment variable to control whether you want to re-create documentation:
// playwright.config.ts
import { defineConfig } from '@playwright/test'
const reporters: any[] = [['html']]
if (process.env.DOCS) {
reporters.push(['casewright'])
}
export default defineConfig({
reporter: reporters,
})Features
Automatic Name Conversion
Casewright automatically converts code identifiers to human-readable text:
submitButton→ "Submit Button"dashboardPage.userProfile→ "User Profile on Dashboard Page"page.goto('/')→ "Navigate to /"
Entity Types
Documentation recognizes four entity types:
- Places: Page Object Models or containers (matched by patterns like
/Page$/) - Elements: Locators on places (e.g., buttons, inputs)
- Actions: Playwright API calls or custom functions
- Variables: Named values passed to actions
Custom Function Documentation
Document custom functions with the @overwrite JSDoc tag:
/**
* @overwrite Check that cards are sorted in {order} order
*/
async function assertCardSorting(page: Page, order: 'asc' | 'desc') {
// implementation
}The {order} placeholder will be replaced with the actual value at runtime.
Ignoring Items
Use the @ignore JSDoc tag to exclude suites, tests, steps, or custom functions from documentation:
/**
* @ignore
*/
test.describe('Technical setup', () => {
// this entire suite is hidden from docs
})
/**
* @ignore
*/
async function internalSetup() {
// calls to this function won't appear as steps
}@ignore works on test.describe, test, test.step, and any custom function. When placed on a suite, all tests inside are ignored as well.
Marking Expectations
Use @expectation to mark a custom function as a verification step. Expectation steps are visually highlighted in the output:
/**
* @overwrite Verify that user {name} is displayed
* @expectation
*/
async function assertUserDisplayed(page: Page, name: string) {
// implementation
}Expectations are also auto-detected for:
- Any
expect()call addDocumentationLinetext starting with "check that"
Documentation Line Helper
Use addDocumentationLine to insert custom text steps that don't correspond to any code:
import { addDocumentationLine } from 'casewright'
test('checkout flow', async ({ page }) => {
await test.step('Complete purchase', async () => {
addDocumentationLine('User has items in cart from previous test')
await checkoutPage.submit()
addDocumentationLine('Check that order confirmation is displayed')
})
})Lines starting with "check that" (case-insensitive) are automatically marked as expectations.
Overwriting Step Documentation
Use overwriteDocumentationLines inside a test.step to replace all auto-detected steps with your own list:
import { overwriteDocumentationLines } from 'casewright'
await test.step('Process complex data', async () => {
overwriteDocumentationLines([
'Fetch data from external API',
'Transform response into table format',
'Check that all rows are valid',
])
// actual implementation — ignored by Casewright
const data = await api.fetch()
const rows = transform(data)
expect(rows.every((r) => r.valid)).toBe(true)
})Documentation Screenshots
Use addDocumentationScreenshot to capture annotated screenshots that appear in the generated docs:
import { addDocumentationScreenshot } from 'casewright'
await test.step('Review dashboard', async () => {
await addDocumentationScreenshot(page, 'dashboard-overview', {
label: 'Dashboard with metrics',
highlight: [{ locator: page.getByTestId('metrics-panel') }],
notes: [
{
text: 'Key metrics section',
target: page.getByTestId('metrics-panel'),
angle: 270, // note above element
},
],
})
})Options:
highlight— elements to outline (configurable border width/color/style)notes— text annotations with arrows pointing to elementsfullPage— capture the full scrollable pagelabel— display text in documentation (defaults to the name)
Interactive HTML Output
Generated documentation includes:
- Collapsible tree view (suites → tests → steps)
- Search and filter functionality
- Status indicators (passed/failed/skipped)
- Dark/light theme toggle
- Duration tracking
- Print-friendly layout
API
Reporter Options
Pass options directly to the reporter:
;[
'casewright',
{
title: 'My Test Documentation',
output: {
dir: './custom-dir',
filename: 'tests.html',
},
places: {
patterns: [/Page$/, /Screen$/],
},
},
]Programmatic Usage
import { generateHtml, createDocModel } from 'casewright'
// Create and populate a doc model
const model = createDocModel()
// ... add suites and tests
// Generate HTML
const html = generateHtml(model, config)CLI Commands
# Create configuration file
npx casewright init
# Show help
npx casewright help
# Show version
npx casewright --versionLicense
MIT
