# Install dependencies
yarn install
# Build the project
yarn build
# Start the application
yarn start
# Start in development mode
yarn dev# Build first
yarn build
# Start with MCP introspection enabled
electron . --enable-mcp-introspection
# Or with custom port
electron . --enable-mcp-introspection --remote-debugging-port=9223- Tests MUST be deterministic - They should produce the same results every time they run
- Tests MUST be independent - Each test should be able to run in isolation without depending on other tests
- Include screenshots - Visual verification is required for UI changes
- Handle asynchronous operations properly - This is an MQTT message queue tool
Structure tests with clear Given-When-Then comments to make them readable:
it('Given a JSON message sent to topic foo/bar/baz, the tree should display nested topics', async function () {
// Given: Mock MQTT publishes JSON to foo/bar/baz
// When: We wait for the topic to appear in the tree
// Then: Topic hierarchy should be visible (foo -> bar -> baz)
})Prefer waitFor over sleep whenever possible:
// ✓ Good: Wait for specific element
const topic = await page.locator('span[data-test-topic="kitchen"]')
await topic.waitFor({ state: 'visible', timeout: 5000 })
// ✗ Bad: Fixed delay without verification
await sleep(5000)Every test should have explicit assertions that verify the expected state:
// ✓ Good: Explicit assertion with meaningful message
const treeNodes = await page.locator('[class*="TreeNode"]')
const count = await treeNodes.count()
expect(count).to.be.greaterThan(0, 'Topic tree should contain nodes')
// ✗ Bad: No assertion, only screenshot
await page.screenshot({ path: 'test.png' })Write tests that describe the data flow:
it('Given messages sent to livingroom/lamp/state and livingroom/lamp/brightness, both should appear under livingroom/lamp', async function () {
// Test implementation verifies the specific data flow
})Leverage data-test-* attributes for reliable selectors:
// ✓ Good: Use data-test attributes
const topic = await page.locator('span[data-test-topic="kitchen"]')
// ⚠ Acceptable: Use role/text when data attributes aren't available
const button = await page.locator('//button/span[contains(text(),"Connect")]')
// ✗ Bad: Rely on CSS classes that may change
const topic = await page.locator('.MuiTreeItem-label')Test should verify both state and UI:
// Verify the action completed
const isVisible = await disconnectButton.isVisible()
expect(isVisible).to.be.true
// Capture screenshot for visual verification
await page.screenshot({ path: 'test-screenshot-connection.png' })Account for message propagation time:
// Publish message
await mockClient.publish('topic/name', 'value')
// Wait for UI to update
await page.locator(`text="value"`).waitFor({ timeout: 5000 })
// Verify state
const value = await page.textContent('.message-value')
expect(value).toBe('value')MQTT is inherently asynchronous. When writing tests:
- Wait for message propagation: Use proper wait strategies (e.g.,
await page.waitForSelector(),await sleep()) - Don't assume immediate updates: Messages take time to send, receive, and update the UI
- Use event-based waiting: Wait for specific UI elements or state changes rather than fixed timeouts when possible
- Account for network latency: MQTT broker communication involves network round trips
// 1. Perform action (e.g., publish message)
await publishMessage(topic, payload)
// 2. Wait for UI to update (not just arbitrary sleep)
await page.waitForSelector(`text="${expectedValue}"`, { timeout: 5000 })
// 3. Verify state
const value = await page.textContent('.message-value')
expect(value).toBe(expectedValue)
// 4. Take screenshot for verification
await page.screenshot({ path: 'test-result.png' })# Run all tests
yarn test
# Run specific test suites
yarn test:app
yarn test:backend
yarn test:mcp
# Run linters
yarn lint
yarn lint:fixThe project supports MCP (Model Context Protocol) for automated testing with Playwright:
- Use
yarn test:mcpto run automated UI tests - Tests launch the app with remote debugging enabled on port 9222
- Connect to
http://localhost:9222via Chrome DevTools Protocol
app/- Frontend React applicationbackend/- Backend models, tests, and connection managementsrc/- Electron main process and bindingssrc/spec/- Test specifications including MCP introspection tests
- Always run
yarn buildbefore starting the application - The app uses Electron (see
package.jsonfor version) - MQTT communication is handled via mqttjs
- All code changes should pass linting (
yarn lint)