Skip to content

Commit

Permalink
dashboard: Add some basic tests for the dashboard (esphome#5870)
Browse files Browse the repository at this point in the history
  • Loading branch information
bdraco authored Dec 6, 2023
1 parent 8f70ef2 commit be07463
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
6 changes: 6 additions & 0 deletions tests/dashboard/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import pathlib


def get_fixture_path(filename: str) -> pathlib.Path:
"""Get path of fixture."""
return pathlib.Path(__file__).parent.joinpath("fixtures", filename)
47 changes: 47 additions & 0 deletions tests/dashboard/fixtures/conf/pico.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
substitutions:
name: picoproxy
friendly_name: Pico Proxy

esphome:
name: ${name}
friendly_name: ${friendly_name}
project:
name: esphome.bluetooth-proxy
version: "1.0"

esp32:
board: esp32dev
framework:
type: esp-idf

wifi:
ap:

api:
logger:
ota:
improv_serial:

dashboard_import:
package_import_url: github://esphome/firmware/bluetooth-proxy/esp32-generic.yaml@main

button:
- platform: factory_reset
id: resetf
- platform: safe_mode
name: Safe Mode Boot
entity_category: diagnostic

sensor:
- platform: template
id: pm11
name: "pm 1.0µm"
lambda: return 1.0;
- platform: template
id: pm251
name: "pm 2.5µm"
lambda: return 2.5;
- platform: template
id: pm101
name: "pm 10µm"
lambda: return 10;
80 changes: 80 additions & 0 deletions tests/dashboard/test_web_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from __future__ import annotations

import asyncio
import json
import os
from unittest.mock import Mock

import pytest
import pytest_asyncio
from tornado.httpclient import AsyncHTTPClient, HTTPResponse
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.testing import bind_unused_port

from esphome.dashboard import web_server
from esphome.dashboard.core import DASHBOARD

from .common import get_fixture_path


class DashboardTestHelper:
def __init__(self, io_loop: IOLoop, client: AsyncHTTPClient, port: int) -> None:
self.io_loop = io_loop
self.client = client
self.port = port

async def fetch(self, path: str, **kwargs) -> HTTPResponse:
"""Get a response for the given path."""
if path.lower().startswith(("http://", "https://")):
url = path
else:
url = f"http://127.0.0.1:{self.port}{path}"
future = self.client.fetch(url, raise_error=True, **kwargs)
result = await future
return result


@pytest_asyncio.fixture()
async def dashboard() -> DashboardTestHelper:
sock, port = bind_unused_port()
args = Mock(
ha_addon=True,
configuration=get_fixture_path("conf"),
port=port,
)
DASHBOARD.settings.parse_args(args)
app = web_server.make_app()
http_server = HTTPServer(app)
http_server.add_sockets([sock])
await DASHBOARD.async_setup()
os.environ["DISABLE_HA_AUTHENTICATION"] = "1"
assert DASHBOARD.settings.using_password is False
assert DASHBOARD.settings.on_ha_addon is True
assert DASHBOARD.settings.using_auth is False
task = asyncio.create_task(DASHBOARD.async_run())
client = AsyncHTTPClient()
io_loop = IOLoop(make_current=False)
yield DashboardTestHelper(io_loop, client, port)
task.cancel()
sock.close()
client.close()
io_loop.close()


@pytest.mark.asyncio
async def test_main_page(dashboard: DashboardTestHelper) -> None:
response = await dashboard.fetch("/")
assert response.code == 200


@pytest.mark.asyncio
async def test_devices_page(dashboard: DashboardTestHelper) -> None:
response = await dashboard.fetch("/devices")
assert response.code == 200
assert response.headers["content-type"] == "application/json"
json_data = json.loads(response.body.decode())
configured_devices = json_data["configured"]
first_device = configured_devices[0]
assert first_device["name"] == "pico"
assert first_device["configuration"] == "pico.yaml"

0 comments on commit be07463

Please sign in to comment.