Testing
Test your LiveViews, components, and forms with djust's testing utilities.
LiveViewTestClient
Test LiveViews without a browser or WebSocket:
fromdjust.testingimport LiveViewTestClient
frommyapp.viewsimport CounterView
deftest_counter():
client = LiveViewTestClient(CounterView)
client.mount()
client.assert_state(count=0)
client.send_event('increment')
client.assert_state(count=1)
html = client.render()
assert 'Count: 1' in html
Test Client Methods
| Method | Description |
|---|---|
mount(**params) |
Initialize the view with parameters |
send_event(event_name, **params) |
Send an event and get the result |
assert_state(**expected) |
Assert state values |
render() |
Get rendered HTML |
With pytest
importpytest
fromdjust.testingimport LiveViewTestClient
@pytest.fixture
defsearch_client():
return LiveViewTestClient(SearchView)
deftest_search(search_client):
search_client.mount()
search_client.send_event('search', query='laptop')
assert len(search_client.state['results']) > 0
With Django TestCase
fromdjango.testimport TestCase
fromdjust.testingimport LiveViewTestClient
classTodoViewTests(TestCase):
defsetUp(self):
self.client = LiveViewTestClient(TodoView)
deftest_add_todo(self):
self.client.mount()
self.client.send_event('add_todo', text='Buy milk')
self.client.assert_state(
todos=[{'text': 'Buy milk', 'done': False}]
)
Testing Forms
deftest_form_validation():
client = LiveViewTestClient(ContactView)
client.mount()
# Test invalid email
client.send_event('validate_field',
field_name='email',
value='invalid')
assert 'email' in client.state['field_errors']
# Test valid submission
client.send_event('submit', data={
'name': 'John',
'email': 'john@example.com',
'message': 'Hello!'
})
assert client.state.get('success_message')
Snapshot Testing
fromdjust.testingimport SnapshotTestMixin
fromdjango.testimport TestCase
classProfileViewSnapshotTests(SnapshotTestMixin, TestCase):
deftest_profile_renders_correctly(self):
client = LiveViewTestClient(ProfileView)
client.mount(user_id=1)
self.assertMatchesSnapshot(
client.render(),
'profile_view'
)
Performance Testing
fromdjust.testingimport performance_test
classPerformanceTests(TestCase):
@performance_test(max_time_ms=100, max_queries=5)
deftest_dashboard_performance(self):
client = LiveViewTestClient(DashboardView)
client.mount()
client.send_event('refresh_data')
Integration Testing
With Selenium
fromdjango.contrib.staticfiles.testingimport StaticLiveServerTestCase
fromseleniumimport webdriver
fromselenium.webdriver.common.byimport By
fromselenium.webdriver.support.uiimport WebDriverWait
fromselenium.webdriver.supportimport expected_conditions as EC
classBrowserTests(StaticLiveServerTestCase):
@classmethod
defsetUpClass(cls):
super().setUpClass()
cls.browser = webdriver.Chrome()
deftest_counter_increments(self):
self.browser.get(f'{self.live_server_url}/counter/')
# Wait for LiveView connection
WebDriverWait(self.browser, 10).until(
EC.presence_of_element_located((By.CSS_SELECTOR, '[dj-connected]'))
)
# Click increment
button = self.browser.find_element(By.CSS_SELECTOR, '[dj-click="increment"]')
button.click()
# Assert updated
WebDriverWait(self.browser, 5).until(
EC.text_to_be_present_in_element((By.CSS_SELECTOR, 'h1'), 'Count: 1')
)
With Playwright
deftest_counter_with_playwright(browser, live_server):
page = browser.new_page()
page.goto(f'{live_server.url}/counter/')
page.wait_for_selector('[dj-connected]')
page.click('[dj-click="increment"]')
page.wait_for_selector('text=Count: 1')
Best Practices
Test State Changes, Not Implementation
# Good
client.mount()
client.send_event('increment')
client.assert_state(count=1)
# Bad
client.mount()
client.view.increment() # Don't call methods directly
Test Edge Cases
deftest_empty_list():
client.mount()
client.assert_state(items=[])
deftest_many_items():
client.mount()
for i in range(100):
client.send_event('add_item', name=f'Item {i}')
assert len(client.state['items']) == 100
Next Steps
- API Reference - Testing API documentation