Home Features Docs Blog Security Examples Quick Start

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