test-cotton-components
Guide AI agents on testing Django Cotton components using django-cotton-bs5 pytest fixtures. Covers when to use cotton_render vs cotton_render_soup vs cotton_render_string vs cotton_render_string_soup, best practices for component testing, DOM assertions, context handling, and multi-component testing patterns. Use when writing or reviewing Cotton component tests.
Best use case
test-cotton-components is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Guide AI agents on testing Django Cotton components using django-cotton-bs5 pytest fixtures. Covers when to use cotton_render vs cotton_render_soup vs cotton_render_string vs cotton_render_string_soup, best practices for component testing, DOM assertions, context handling, and multi-component testing patterns. Use when writing or reviewing Cotton component tests.
Teams using test-cotton-components should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/test-cotton-components/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How test-cotton-components Compares
| Feature / Agent | test-cotton-components | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Guide AI agents on testing Django Cotton components using django-cotton-bs5 pytest fixtures. Covers when to use cotton_render vs cotton_render_soup vs cotton_render_string vs cotton_render_string_soup, best practices for component testing, DOM assertions, context handling, and multi-component testing patterns. Use when writing or reviewing Cotton component tests.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Test Cotton Components
A comprehensive guide for AI agents on effectively using django-cotton-bs5 pytest fixtures to test Django Cotton components. This skill teaches fixture selection, testing patterns, and best practices.
## When to Use This Skill
- Writing new tests for Django Cotton components
- Testing Bootstrap 5 components wrapped in Cotton syntax
- Reviewing or refactoring existing Cotton component tests
- User asks: "How do I test Cotton components?", "Which fixture should I use?", "Test this component"
- Debugging test failures in Cotton-based templates
## Prerequisites
- Project has `django-cotton-bs5` installed (provides pytest fixtures automatically)
- Django and pytest configured in the project
- Basic understanding of Django templates and Cotton component syntax
## Available Fixtures
### Fixture Decision Matrix
| Scenario | Input | Fixture | Output |
|----------|-------|---------|--------|
| Test single component by name | `'cotton_bs5.alert'` | `cotton_render` | Raw HTML string |
| Test single component with DOM queries | `'cotton_bs5.button'` | `cotton_render_soup` | BeautifulSoup object |
| Test inline multi-component markup | `"<c-ul><c-li /></c-ul>"` | `cotton_render_string` | Raw HTML string |
| Test complex nested structure with DOM queries | `"<c-card><c-button /></c-card>"` | `cotton_render_string_soup` | BeautifulSoup object |
### Quick Rules
1. **Use `_soup` variants when you need DOM traversal** (`find`, `find_all`, `select`, etc.)
2. **Use `_string` variants when testing multiple components together** or inline markup
3. **Use plain variants for simple string assertions** ("does it contain X?")
4. **All fixtures inject request object automatically** — don't create one manually
## Testing Patterns
### Pattern 1: Single Component - Basic Assertions
**Use Case**: Verify a component renders with correct CSS classes and content.
**Fixture**: `cotton_render` (raw HTML)
```python
def test_alert_renders_with_variant(cotton_render):
"""Test alert component renders correct variant class."""
html = cotton_render(
'cotton_bs5.alert',
message="Warning message",
variant="warning"
)
# Simple string assertions
assert 'alert-warning' in html
assert 'Warning message' in html
assert 'alert' in html
```
**When to use**:
- Testing CSS class presence
- Verifying text content appears
- Quick smoke tests
- Testing component attributes are rendered
---
### Pattern 2: Single Component - DOM Structure
**Use Case**: Verify component structure, hierarchy, or specific element attributes.
**Fixture**: `cotton_render_soup` (parsed HTML)
```python
def test_button_structure_and_attributes(cotton_render_soup):
"""Test button component renders correct HTML structure."""
soup = cotton_render_soup(
'cotton_bs5.button',
text="Click Me",
variant="primary",
size="lg"
)
# DOM traversal and assertions
button = soup.find('button')
assert button is not None
assert 'btn' in button['class']
assert 'btn-primary' in button['class']
assert 'btn-lg' in button['class']
assert button.get_text().strip() == 'Click Me'
```
**When to use**:
- Verifying element attributes (id, class, data-*, aria-*)
- Testing DOM hierarchy (parent/child relationships)
- Checking element counts (`len(soup.find_all('li'))`)
- Extracting and validating specific text content
---
### Pattern 3: Multi-Component - Inline Markup
**Use Case**: Test how multiple components work together in a template string.
**Fixture**: `cotton_render_string` (compiles Cotton syntax → raw HTML)
```python
def test_list_with_multiple_items(cotton_render_string):
"""Test list group with multiple items renders correctly."""
html = cotton_render_string("""
<c-list_group>
<c-list_group.item text="First Item" />
<c-list_group.item text="Second Item" active="True" />
<c-list_group.item text="Third Item" />
</c-list_group>
""")
# Verify all items present
assert 'First Item' in html
assert 'Second Item' in html
assert 'Third Item' in html
assert 'active' in html # Active state rendered
```
**When to use**:
- Testing component composition
- Verifying parent-child component relationships
- Testing slot content with nested components
- Quick inline component experiments
---
### Pattern 4: Multi-Component - Complex Structure Testing
**Use Case**: Test nested components with DOM queries and assertions on structure.
**Fixture**: `cotton_render_string_soup` (compiles + parses)
```python
def test_card_with_nested_components(cotton_render_string_soup):
"""Test card component with nested title, body, and buttons."""
soup = cotton_render_string_soup("""
<c-card>
<c-card.title>User Profile</c-card.title>
<c-card.body>
<p>Manage your account settings</p>
<c-button variant='primary'>Edit Profile</c-button>
<c-button variant='secondary'>Cancel</c-button>
</c-card.body>
</c-card>
""")
# Test structure
card = soup.find('div', class_='card')
assert card is not None
# Test title
title = card.find('h5')
assert title.get_text().strip() == 'User Profile'
# Test buttons
buttons = card.find_all('button')
assert len(buttons) == 2
assert 'btn-primary' in buttons[0]['class']
assert buttons[0].get_text().strip() == 'Edit Profile'
assert 'btn-secondary' in buttons[1]['class']
```
**When to use**:
- Testing complex component hierarchies
- Verifying nested component relationships
- Counting child elements
- Testing layouts (cards, modals, accordions with nested content)
---
### Pattern 5: Context Variables & Cotton Attributes
**Use Case**: Test that global context and component-level attributes work together without leakage.
**Fixture**: `cotton_render_string` or `cotton_render_string_soup` (with context parameter)
```python
def test_component_with_global_context(cotton_render_string_soup):
"""Test component uses both global context and Cotton attributes."""
template = """
<c-alert variant='{{ alert_type }}'>
{{ message }}
</c-alert>
<c-button variant='primary'>{{ button_text }}</c-button>
"""
soup = cotton_render_string_soup(template, context={
'alert_type': 'success',
'message': 'Operation completed',
'button_text': 'Continue'
})
# Verify context variables applied
alert = soup.find('div', class_='alert')
assert 'alert-success' in alert['class']
assert 'Operation completed' in alert.get_text()
button = soup.find('button')
assert 'Continue' in button.get_text()
```
**When to use**:
- Testing components with dynamic attributes
- Verifying template variable interpolation
- Testing context isolation (no leakage between components)
- Integration testing with Django views
---
## Best Practices
### ✅ DO
1. **Use the simplest fixture that meets your needs**
- `cotton_render` for simple assertions → faster
- `cotton_render_soup` when you need DOM queries
2. **Test one concern per test function**
```python
# Good: focused test
def test_button_variant_primary(cotton_render):
html = cotton_render('cotton_bs5.button', variant='primary')
assert 'btn-primary' in html
# Good: separate test for size
def test_button_size_large(cotton_render):
html = cotton_render('cotton_bs5.button', size='lg')
assert 'btn-lg' in html
```
3. **Use descriptive test names and docstrings**
```python
def test_alert_dismissible_renders_close_button(cotton_render_soup):
"""Test that dismissible alerts include a close button with correct aria-label."""
soup = cotton_render_soup('cotton_bs5.alert', dismissible=True)
# ...
```
4. **Test accessibility attributes**
```python
def test_modal_has_aria_labels(cotton_render_soup):
"""Verify modal has proper ARIA attributes for screen readers."""
soup = cotton_render_soup('cotton_bs5.modal', id='myModal')
modal = soup.find('div', class_='modal')
assert modal.get('aria-labelledby') is not None
assert modal.get('role') == 'dialog'
```
5. **Test negative cases (attributes NOT present)**
```python
def test_button_without_icon_has_no_icon_element(cotton_render_soup):
"""Verify button without icon doesn't render icon element."""
soup = cotton_render_soup('cotton_bs5.button', text='Click')
icon = soup.find('i') # or svg, depending on icon implementation
assert icon is None
```
### ❌ DON'T
1. **Don't create request objects manually** — fixtures handle it
```python
# Bad
def test_component(cotton_render):
request = RequestFactory().get("/") # Unnecessary!
# ...
# Good
def test_component(cotton_render):
html = cotton_render('component_name')
# ...
```
2. **Don't use `cotton_render_soup` for simple string checks**
```python
# Inefficient - parsing overhead
def test_alert_has_text(cotton_render_soup):
soup = cotton_render_soup('cotton_bs5.alert', message='Hello')
assert 'Hello' in str(soup)
# Better - direct string assertion
def test_alert_has_text(cotton_render):
html = cotton_render('cotton_bs5.alert', message='Hello')
assert 'Hello' in html
```
3. **Don't test Bootstrap CSS implementation details** — test your component's behavior
```python
# Bad - too brittle, tests Bootstrap internals
def test_button_has_exact_padding():
assert 'padding: 0.375rem 0.75rem' in html
# Good - test component renders correct classes
def test_button_applies_size_class(cotton_render):
html = cotton_render('cotton_bs5.button', size='sm')
assert 'btn-sm' in html
```
4. **Don't duplicate tests across fixtures** unless testing different aspects
```python
# Bad - redundant
def test_alert_with_render(cotton_render):
html = cotton_render('cotton_bs5.alert')
assert 'alert' in html
def test_alert_with_soup(cotton_render_soup): # Same test!
soup = cotton_render_soup('cotton_bs5.alert')
assert 'alert' in str(soup)
# Good - different concerns
def test_alert_css_class(cotton_render):
html = cotton_render('cotton_bs5.alert')
assert 'alert' in html
def test_alert_structure(cotton_render_soup):
soup = cotton_render_soup('cotton_bs5.alert')
alert_div = soup.find('div', class_='alert')
assert alert_div.get('role') == 'alert'
```
---
## Common Testing Scenarios
### Testing Slots (Named and Default)
```python
def test_button_slot_content(cotton_render_string_soup):
"""Test button with slot content instead of text attribute."""
soup = cotton_render_string_soup("""
<c-button variant='primary'>
<i class='icon-save'></i> Save Changes
</c-button>
""")
button = soup.find('button')
assert button.find('i', class_='icon-save') is not None
assert 'Save Changes' in button.get_text()
```
### Testing Conditional Rendering
```python
def test_alert_dismissible_button(cotton_render_soup):
"""Test close button only appears when dismissible=True."""
# With dismissible
soup = cotton_render_soup('cotton_bs5.alert', dismissible=True)
assert soup.find('button', class_='btn-close') is not None
# Without dismissible
soup = cotton_render_soup('cotton_bs5.alert', dismissible=False)
assert soup.find('button', class_='btn-close') is None
```
### Testing Dynamic Classes
```python
def test_button_combines_variant_and_size(cotton_render_soup):
"""Test button correctly combines variant and size classes."""
soup = cotton_render_soup(
'cotton_bs5.button',
variant='success',
size='lg'
)
button = soup.find('button')
classes = button['class']
assert 'btn' in classes
assert 'btn-success' in classes
assert 'btn-lg' in classes
```
### Testing Data Attributes
```python
def test_modal_data_attributes(cotton_render_soup):
"""Test modal renders correct data-bs-* attributes."""
soup = cotton_render_soup('cotton_bs5.modal', id='testModal')
toggle_button = soup.find('button', attrs={'data-bs-toggle': 'modal'})
assert toggle_button is not None
assert toggle_button.get('data-bs-target') == '#testModal'
```
---
## Troubleshooting
### Issue: "Fixture not found"
**Problem**: Test can't find cotton fixtures.
**Solution**: Ensure `django-cotton-bs5` is installed and pytest can discover it:
```bash
pip install django-cotton-bs5
pytest --fixtures | grep cotton_render
```
All four fixtures should appear. If not, check `INSTALLED_APPS` includes `cotton_bs5`.
---
### Issue: "Template syntax error"
**Problem**: Cotton syntax not compiling in `cotton_render_string`.
**Solution**:
1. Check your Cotton component syntax is valid
2. Verify component is registered in Django
3. Test component works in actual template first
4. Use `cotton_render('component.name')` to isolate if issue is component vs string rendering
---
### Issue: "Can't find element with BeautifulSoup"
**Problem**: `soup.find()` returns `None`.
**Solution**:
1. Print the HTML to inspect structure: `print(soup.prettify())`
2. Check if component rendered at all
3. Verify CSS selector or attributes are correct
4. Component might use different tag than expected
```python
# Debug: print HTML structure
def test_debug_component(cotton_render_soup):
soup = cotton_render_soup('cotton_bs5.card')
print(soup.prettify()) # Inspect actual output
# Now adjust assertions based on what you see
```
---
### Issue: "Context variable not rendering"
**Problem**: Template variables like `{{ variable }}` show as literal text.
**Solution**: Pass context dict to fixture:
```python
# Wrong - variable won't render
html = cotton_render_string("<c-alert>{{ msg }}</c-alert>")
# Right - pass context
html = cotton_render_string(
"<c-alert>{{ msg }}</c-alert>",
context={'msg': 'Hello'}
)
```
---
## Example: Complete Test Suite for a Component
```python
"""Test suite for Button component."""
import pytest
class TestButtonComponent:
"""Test cotton_bs5.button component."""
def test_button_basic_rendering(self, cotton_render):
"""Test button renders with default classes."""
html = cotton_render('cotton_bs5.button', text='Click')
assert 'btn' in html
assert 'Click' in html
def test_button_variants(self, cotton_render):
"""Test button renders all Bootstrap variants."""
variants = ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark']
for variant in variants:
html = cotton_render('cotton_bs5.button', variant=variant)
assert f'btn-{variant}' in html
def test_button_sizes(self, cotton_render_soup):
"""Test button renders with size classes."""
# Small
soup = cotton_render_soup('cotton_bs5.button', size='sm')
assert 'btn-sm' in soup.find('button')['class']
# Large
soup = cotton_render_soup('cotton_bs5.button', size='lg')
assert 'btn-lg' in soup.find('button')['class']
def test_button_as_link(self, cotton_render_soup):
"""Test button renders as anchor tag when href provided."""
soup = cotton_render_soup('cotton_bs5.button', href='/test/', text='Link')
link = soup.find('a')
assert link is not None
assert link.get('href') == '/test/'
assert 'btn' in link['class']
def test_button_disabled(self, cotton_render_soup):
"""Test button disabled attribute."""
soup = cotton_render_soup('cotton_bs5.button', disabled=True)
button = soup.find('button')
assert button.get('disabled') is not None
def test_button_with_icon_slot(self, cotton_render_string_soup):
"""Test button with icon in slot content."""
soup = cotton_render_string_soup("""
<c-button variant='primary'>
<i class='bi bi-save'></i> Save
</c-button>
""")
button = soup.find('button')
icon = button.find('i', class_='bi-save')
assert icon is not None
assert 'Save' in button.get_text()
```
---
## Summary
Use this skill to guide fixture selection and write comprehensive, maintainable tests for Django Cotton components. Remember:
- **Start simple**: Use `cotton_render` for basic tests
- **Use BeautifulSoup** (`_soup`) when you need DOM queries
- **Test multi-component scenarios** with `cotton_render_string` variants
- **Test accessibility** (ARIA attributes, roles, labels)
- **Follow one-concern-per-test** principle
- **Document expected behavior** in docstrings
The fixtures make testing Cotton components straightforward — choose the right tool for each testing need!Related Skills
webrtc-timing-test
Measure WebRTC connection timing on Daily rooms. Use when testing Daily video call connection performance, measuring ICE negotiation time, benchmarking WebRTC setup latency, or when asked to test how long a Daily room takes to connect.
web-testing
Playwright automation, Chrome DevTools debugging, and browser interaction testing. Use for E2E/unit tests, capturing screenshots, inspecting network/console logs, or validating user flows in web applications.
qa-testing-mobile
Mobile app testing strategy and execution for iOS and Android (native + cross-platform): choose automation frameworks, define device matrix, control flakes, validate performance/reliability/accessibility, and set CI + release gates. Use when you need a mobile QA plan, device lab/CI setup, or guidance on XCUITest/Espresso/Appium/Detox/Maestro/Flutter testing.
app-test-workflow
Flutter 앱 테스트 워크플로우를 시작합니다. 테스트 계획 수립 -> 에뮬레이터 테스트 -> 실패 시 디버그 수정 -> 재테스트 순서로 진행합니다. "앱 테스트 워크플로우", "/app-test-workflow", "앱 테스트" 등의 명령으로 활성화됩니다.
anthropic-webapp-testing
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
anthropic-web-testing
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
pcf-code-components
Understanding code components structure and implementation Triggers on: **/*.{ts,tsx,js,json,xml,pcfproj,csproj}
Next.js App Router & Server Components
Build Next.js 15 applications using App Router, Server Components, Client Components, Server Actions, and streaming. Apply when creating pages, handling data fetching, implementing routes, or optimizing performance.
hig-components-system
Apple HIG guidance for system experience components: widgets, live activities, notifications, complications, home screen quick actions, top shelf, watch faces, app clips, and app shortcuts.
hig-components-status
Apple HIG guidance for status and progress UI components including progress indicators, status bars, and activity rings.
hig-components-search
Apple HIG guidance for navigation-related components including search fields, page controls, and path controls.
hig-components-menus
Apple HIG guidance for menu and button components including menus, context menus, dock menus, edit menus, the menu bar, toolbars, action buttons, pop-up buttons, pull-down buttons, disclosure...