Files
homeassistant-mcp/testing/index.html
2025-02-05 19:32:38 +00:00

2835 lines
96 KiB
HTML

<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="canonical" href="https://jango-blockchained.github.io/advanced-homeassitant-mcp/testing/">
<link rel="prev" href="../development/tools/">
<link rel="next" href="../architecture/">
<link rel="icon" href="../assets/images/favicon.ico">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.2">
<title>Testing Guide - Advanced Home Assistant MCP</title>
<link rel="stylesheet" href="../assets/stylesheets/main.d7758b05.min.css">
<link rel="stylesheet" href="../assets/stylesheets/palette.06af60db.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../assets/_mkdocstrings.css">
<link rel="stylesheet" href="../stylesheets/extra.css">
<script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<script id="__analytics">function __md_analytics(){function e(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],e("js",new Date),e("config",""),document.addEventListener("DOMContentLoaded",(function(){document.forms.search&&document.forms.search.query.addEventListener("blur",(function(){this.value&&e("event","search",{search_term:this.value})}));document$.subscribe((function(){var t=document.forms.feedback;if(void 0!==t)for(var a of t.querySelectorAll("[type=submit]"))a.addEventListener("click",(function(a){a.preventDefault();var n=document.location.pathname,d=this.getAttribute("data-md-value");e("event","feedback",{page:n,data:d}),t.firstElementChild.disabled=!0;var r=t.querySelector(".md-feedback__note [data-md-value='"+d+"']");r&&(r.hidden=!1)})),t.hidden=!1})),location$.subscribe((function(t){e("config","",{page_path:t.pathname})}))}));var t=document.createElement("script");t.async=!0,t.src="https://www.googletagmanager.com/gtag/js?id=",document.getElementById("__analytics").insertAdjacentElement("afterEnd",t)}</script>
<script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#testing-documentation" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="Advanced Home Assistant MCP" class="md-header__button md-logo" aria-label="Advanced Home Assistant MCP" data-md-component="logo">
<img src="../assets/images/logo.png" alt="logo">
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
Advanced Home Assistant MCP
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Testing Guide
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
<input class="md-option" data-md-color-media="" data-md-color-scheme="slate" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/jango-blockchained/advanced-homeassitant-mcp" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="Advanced Home Assistant MCP" class="md-nav__button md-logo" aria-label="Advanced Home Assistant MCP" data-md-component="logo">
<img src="../assets/images/logo.png" alt="logo">
</a>
Advanced Home Assistant MCP
</label>
<div class="md-nav__source">
<a href="https://github.com/jango-blockchained/advanced-homeassitant-mcp" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M439.55 236.05 244 40.45a28.87 28.87 0 0 0-40.81 0l-40.66 40.63 51.52 51.52c27.06-9.14 52.68 16.77 43.39 43.68l49.66 49.66c34.23-11.8 61.18 31 35.47 56.69-26.49 26.49-70.21-2.87-56-37.34L240.22 199v121.85c25.3 12.54 22.26 41.85 9.08 55a34.34 34.34 0 0 1-48.55 0c-17.57-17.6-11.07-46.91 11.25-56v-123c-20.8-8.51-24.6-30.74-18.64-45L142.57 101 8.45 235.14a28.86 28.86 0 0 0 0 40.81l195.61 195.6a28.86 28.86 0 0 0 40.8 0l194.69-194.69a28.86 28.86 0 0 0 0-40.81"/></svg>
</div>
<div class="md-source__repository">
GitHub
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../usage/" class="md-nav__link">
<span class="md-ellipsis">
Usage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../api/" class="md-nav__link">
<span class="md-ellipsis">
API
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_4" >
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="">
<span class="md-ellipsis">
Configuration
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../claude_desktop_config.md" class="md-nav__link">
<span class="md-ellipsis">
Claude Desktop Config
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cline_config.md" class="md-nav__link">
<span class="md-ellipsis">
Cline Config
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
Getting Started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../getting-started/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../getting-started/installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../getting-started/configuration/" class="md-nav__link">
<span class="md-ellipsis">
Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../getting-started/docker/" class="md-nav__link">
<span class="md-ellipsis">
Docker Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../getting-started/quickstart/" class="md-nav__link">
<span class="md-ellipsis">
Quick Start
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_6" >
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="">
<span class="md-ellipsis">
API Reference
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
API Reference
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../api/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../api/" class="md-nav__link">
<span class="md-ellipsis">
API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../api/sse/" class="md-nav__link">
<span class="md-ellipsis">
SSE API
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../api/core/" class="md-nav__link">
<span class="md-ellipsis">
Core Functions
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="">
<span class="md-ellipsis">
Tools
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Tools
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/tools/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_2" >
<label class="md-nav__link" for="__nav_7_2" id="__nav_7_2_label" tabindex="0">
<span class="md-ellipsis">
Device Management
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_2">
<span class="md-nav__icon md-icon"></span>
Device Management
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/device-management/list-devices/" class="md-nav__link">
<span class="md-ellipsis">
List Devices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/device-management/control/" class="md-nav__link">
<span class="md-ellipsis">
Device Control
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_3" >
<label class="md-nav__link" for="__nav_7_3" id="__nav_7_3_label" tabindex="0">
<span class="md-ellipsis">
History & State
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_3">
<span class="md-nav__icon md-icon"></span>
History & State
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/history-state/history/" class="md-nav__link">
<span class="md-ellipsis">
History
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/history-state/scene/" class="md-nav__link">
<span class="md-ellipsis">
Scene Management
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_4" >
<label class="md-nav__link" for="__nav_7_4" id="__nav_7_4_label" tabindex="0">
<span class="md-ellipsis">
Automation
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_4">
<span class="md-nav__icon md-icon"></span>
Automation
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/automation/automation/" class="md-nav__link">
<span class="md-ellipsis">
Automation Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/automation/automation-config/" class="md-nav__link">
<span class="md-ellipsis">
Automation Configuration
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_5" >
<label class="md-nav__link" for="__nav_7_5" id="__nav_7_5_label" tabindex="0">
<span class="md-ellipsis">
Add-ons & Packages
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_5">
<span class="md-nav__icon md-icon"></span>
Add-ons & Packages
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/addons-packages/addon/" class="md-nav__link">
<span class="md-ellipsis">
Add-on Management
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/addons-packages/package/" class="md-nav__link">
<span class="md-ellipsis">
Package Management
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_6" >
<label class="md-nav__link" for="__nav_7_6" id="__nav_7_6_label" tabindex="0">
<span class="md-ellipsis">
Notifications
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_6">
<span class="md-nav__icon md-icon"></span>
Notifications
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/notifications/notify/" class="md-nav__link">
<span class="md-ellipsis">
Notify
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_7_7" >
<label class="md-nav__link" for="__nav_7_7" id="__nav_7_7_label" tabindex="0">
<span class="md-ellipsis">
Events
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_7">
<span class="md-nav__icon md-icon"></span>
Events
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../tools/events/subscribe-events/" class="md-nav__link">
<span class="md-ellipsis">
Event Subscription
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/events/sse-stats/" class="md-nav__link">
<span class="md-ellipsis">
SSE Statistics
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" checked>
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="">
<span class="md-ellipsis">
Development
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
Development
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../development/development/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../development/best-practices/" class="md-nav__link">
<span class="md-ellipsis">
Best Practices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../development/interfaces/" class="md-nav__link">
<span class="md-ellipsis">
Interfaces
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../development/tools/" class="md-nav__link">
<span class="md-ellipsis">
Tool Development
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Testing Guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Testing Guide
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#quick-reference" class="md-nav__link">
<span class="md-ellipsis">
Quick Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-structure" class="md-nav__link">
<span class="md-ellipsis">
Test Structure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-configuration" class="md-nav__link">
<span class="md-ellipsis">
Test Configuration
</span>
</a>
<nav class="md-nav" aria-label="Test Configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#bun-test-configuration-bunfigtoml" class="md-nav__link">
<span class="md-ellipsis">
Bun Test Configuration (bunfig.toml)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bun-scripts" class="md-nav__link">
<span class="md-ellipsis">
Bun Scripts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#test-setup" class="md-nav__link">
<span class="md-ellipsis">
Test Setup
</span>
</a>
<nav class="md-nav" aria-label="Test Setup">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#global-configuration" class="md-nav__link">
<span class="md-ellipsis">
Global Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-environment" class="md-nav__link">
<span class="md-ellipsis">
Test Environment
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#running-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#advanced-debugging" class="md-nav__link">
<span class="md-ellipsis">
Advanced Debugging
</span>
</a>
<nav class="md-nav" aria-label="Advanced Debugging">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-node-inspector" class="md-nav__link">
<span class="md-ellipsis">
Using Node Inspector
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#using-vs-code" class="md-nav__link">
<span class="md-ellipsis">
Using VS Code
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-isolation" class="md-nav__link">
<span class="md-ellipsis">
Test Isolation
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#writing-tests" class="md-nav__link">
<span class="md-ellipsis">
Writing Tests
</span>
</a>
<nav class="md-nav" aria-label="Writing Tests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-file-naming" class="md-nav__link">
<span class="md-ellipsis">
Test File Naming
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#example-test-structure" class="md-nav__link">
<span class="md-ellipsis">
Example Test Structure
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#coverage" class="md-nav__link">
<span class="md-ellipsis">
Coverage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#security-middleware-testing" class="md-nav__link">
<span class="md-ellipsis">
Security Middleware Testing
</span>
</a>
<nav class="md-nav" aria-label="Security Middleware Testing">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#utility-function-testing" class="md-nav__link">
<span class="md-ellipsis">
Utility Function Testing
</span>
</a>
<nav class="md-nav" aria-label="Utility Function Testing">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#key-utility-functions" class="md-nav__link">
<span class="md-ellipsis">
Key Utility Functions
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#testing-philosophy" class="md-nav__link">
<span class="md-ellipsis">
Testing Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#best-practices" class="md-nav__link">
<span class="md-ellipsis">
Best Practices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#running-security-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Security Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#continuous-improvement" class="md-nav__link">
<span class="md-ellipsis">
Continuous Improvement
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#best-practices_1" class="md-nav__link">
<span class="md-ellipsis">
Best Practices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#coverage_1" class="md-nav__link">
<span class="md-ellipsis">
Coverage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging-tests" class="md-nav__link">
<span class="md-ellipsis">
Debugging Tests
</span>
</a>
<nav class="md-nav" aria-label="Debugging Tests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#advanced-debugging_1" class="md-nav__link">
<span class="md-ellipsis">
Advanced Debugging
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#contributing" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#coverage-requirements" class="md-nav__link">
<span class="md-ellipsis">
Coverage Requirements
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../troubleshooting/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle md-toggle--indeterminate" type="checkbox" id="__nav_12" >
<label class="md-nav__link" for="__nav_12" id="__nav_12_label" tabindex="">
<span class="md-ellipsis">
Examples
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_12_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_12">
<span class="md-nav__icon md-icon"></span>
Examples
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../examples/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../roadmap/" class="md-nav__link">
<span class="md-ellipsis">
Roadmap
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#quick-reference" class="md-nav__link">
<span class="md-ellipsis">
Quick Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#overview" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-structure" class="md-nav__link">
<span class="md-ellipsis">
Test Structure
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-configuration" class="md-nav__link">
<span class="md-ellipsis">
Test Configuration
</span>
</a>
<nav class="md-nav" aria-label="Test Configuration">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#bun-test-configuration-bunfigtoml" class="md-nav__link">
<span class="md-ellipsis">
Bun Test Configuration (bunfig.toml)
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#bun-scripts" class="md-nav__link">
<span class="md-ellipsis">
Bun Scripts
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#test-setup" class="md-nav__link">
<span class="md-ellipsis">
Test Setup
</span>
</a>
<nav class="md-nav" aria-label="Test Setup">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#global-configuration" class="md-nav__link">
<span class="md-ellipsis">
Global Configuration
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-environment" class="md-nav__link">
<span class="md-ellipsis">
Test Environment
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#running-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#advanced-debugging" class="md-nav__link">
<span class="md-ellipsis">
Advanced Debugging
</span>
</a>
<nav class="md-nav" aria-label="Advanced Debugging">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#using-node-inspector" class="md-nav__link">
<span class="md-ellipsis">
Using Node Inspector
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#using-vs-code" class="md-nav__link">
<span class="md-ellipsis">
Using VS Code
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#test-isolation" class="md-nav__link">
<span class="md-ellipsis">
Test Isolation
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#writing-tests" class="md-nav__link">
<span class="md-ellipsis">
Writing Tests
</span>
</a>
<nav class="md-nav" aria-label="Writing Tests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#test-file-naming" class="md-nav__link">
<span class="md-ellipsis">
Test File Naming
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#example-test-structure" class="md-nav__link">
<span class="md-ellipsis">
Example Test Structure
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#coverage" class="md-nav__link">
<span class="md-ellipsis">
Coverage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#security-middleware-testing" class="md-nav__link">
<span class="md-ellipsis">
Security Middleware Testing
</span>
</a>
<nav class="md-nav" aria-label="Security Middleware Testing">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#utility-function-testing" class="md-nav__link">
<span class="md-ellipsis">
Utility Function Testing
</span>
</a>
<nav class="md-nav" aria-label="Utility Function Testing">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#key-utility-functions" class="md-nav__link">
<span class="md-ellipsis">
Key Utility Functions
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#testing-philosophy" class="md-nav__link">
<span class="md-ellipsis">
Testing Philosophy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#best-practices" class="md-nav__link">
<span class="md-ellipsis">
Best Practices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#running-security-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Security Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#continuous-improvement" class="md-nav__link">
<span class="md-ellipsis">
Continuous Improvement
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#best-practices_1" class="md-nav__link">
<span class="md-ellipsis">
Best Practices
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#coverage_1" class="md-nav__link">
<span class="md-ellipsis">
Coverage
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging-tests" class="md-nav__link">
<span class="md-ellipsis">
Debugging Tests
</span>
</a>
<nav class="md-nav" aria-label="Debugging Tests">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#advanced-debugging_1" class="md-nav__link">
<span class="md-ellipsis">
Advanced Debugging
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#contributing" class="md-nav__link">
<span class="md-ellipsis">
Contributing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#coverage-requirements" class="md-nav__link">
<span class="md-ellipsis">
Coverage Requirements
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="testing-documentation">Testing Documentation</h1>
<h2 id="quick-reference">Quick Reference</h2>
<div class="highlight"><pre><span></span><code><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="c1"># Most Common Commands</span>
<a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span><span class="c1"># Run all tests</span>
<a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--watch<span class="w"> </span><span class="c1"># Run tests in watch mode</span>
<a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage<span class="w"> </span><span class="c1"># Run tests with coverage</span>
<a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>path/to/test.ts<span class="w"> </span><span class="c1"># Run a specific test file</span>
<a id="__codelineno-0-6" name="__codelineno-0-6" href="#__codelineno-0-6"></a>
<a id="__codelineno-0-7" name="__codelineno-0-7" href="#__codelineno-0-7"></a><span class="c1"># Additional Options</span>
<a id="__codelineno-0-8" name="__codelineno-0-8" href="#__codelineno-0-8"></a><span class="nv">DEBUG</span><span class="o">=</span><span class="nb">true</span><span class="w"> </span>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span><span class="c1"># Run with debug output</span>
<a id="__codelineno-0-9" name="__codelineno-0-9" href="#__codelineno-0-9"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--pattern<span class="w"> </span><span class="s2">&quot;auth&quot;</span><span class="w"> </span><span class="c1"># Run tests matching a pattern</span>
<a id="__codelineno-0-10" name="__codelineno-0-10" href="#__codelineno-0-10"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--timeout<span class="w"> </span><span class="m">60000</span><span class="w"> </span><span class="c1"># Run with a custom timeout</span>
</code></pre></div>
<h2 id="overview">Overview</h2>
<p>This document describes the testing setup and practices used in the Home Assistant MCP project. We use Bun's test runner for both unit and integration testing, ensuring comprehensive coverage across modules.</p>
<h2 id="test-structure">Test Structure</h2>
<p>Tests are organized in two main locations:</p>
<ol>
<li><strong>Root Level Integration Tests</strong> (<code>/__tests__/</code>):</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>__tests__/
<a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>├── ai/ # AI/ML component tests
<a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a>├── api/ # API integration tests
<a id="__codelineno-1-4" name="__codelineno-1-4" href="#__codelineno-1-4"></a>├── context/ # Context management tests
<a id="__codelineno-1-5" name="__codelineno-1-5" href="#__codelineno-1-5"></a>├── hass/ # Home Assistant integration tests
<a id="__codelineno-1-6" name="__codelineno-1-6" href="#__codelineno-1-6"></a>├── schemas/ # Schema validation tests
<a id="__codelineno-1-7" name="__codelineno-1-7" href="#__codelineno-1-7"></a>├── security/ # Security integration tests
<a id="__codelineno-1-8" name="__codelineno-1-8" href="#__codelineno-1-8"></a>├── tools/ # Tools and utilities tests
<a id="__codelineno-1-9" name="__codelineno-1-9" href="#__codelineno-1-9"></a>├── websocket/ # WebSocket integration tests
<a id="__codelineno-1-10" name="__codelineno-1-10" href="#__codelineno-1-10"></a>├── helpers.test.ts # Helper function tests
<a id="__codelineno-1-11" name="__codelineno-1-11" href="#__codelineno-1-11"></a>├── index.test.ts # Main application tests
<a id="__codelineno-1-12" name="__codelineno-1-12" href="#__codelineno-1-12"></a>└── server.test.ts # Server integration tests
</code></pre></div>
<ol>
<li><strong>Component Level Unit Tests</strong> (<code>src/**/</code>):</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>src/
<a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>├── __tests__/ # Global test setup and utilities
<a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>│ └── setup.ts # Global test configuration
<a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>├── component/
<a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a>│ ├── __tests__/ # Component-specific unit tests
<a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a>│ └── component.ts
</code></pre></div>
<h2 id="test-configuration">Test Configuration</h2>
<h3 id="bun-test-configuration-bunfigtoml">Bun Test Configuration (<code>bunfig.toml</code>)</h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a><span class="k">[test]</span>
<a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a><span class="n">preload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;./src/__tests__/setup.ts&quot;</span><span class="p">]</span><span class="w"> </span><span class="c1"># Global test setup</span>
<a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a><span class="n">coverage</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c1"># Enable coverage by default</span>
<a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a><span class="n">timeout</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">30000</span><span class="w"> </span><span class="c1"># Test timeout in milliseconds</span>
<a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a><span class="n">testMatch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;**/__tests__/**/*.test.ts&quot;</span><span class="p">]</span><span class="w"> </span><span class="c1"># Test file patterns</span>
</code></pre></div>
<h3 id="bun-scripts">Bun Scripts</h3>
<p>Available test commands in <code>package.json</code>:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="c1"># Run all tests</span>
<a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a>bun<span class="w"> </span><span class="nb">test</span>
<a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a>
<a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="c1"># Watch mode for development</span>
<a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--watch
<a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a>
<a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="c1"># Generate coverage report</span>
<a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage
<a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a>
<a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a><span class="c1"># Run linting</span>
<a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a>bun<span class="w"> </span>run<span class="w"> </span>lint
<a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a>
<a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a><span class="c1"># Format code</span>
<a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a>bun<span class="w"> </span>run<span class="w"> </span>format
</code></pre></div>
<h2 id="test-setup">Test Setup</h2>
<h3 id="global-configuration">Global Configuration</h3>
<p>A global test setup file (<code>src/__tests__/setup.ts</code>) provides:
- Environment configuration
- Mock utilities
- Test helper functions
- Global lifecycle hooks</p>
<h3 id="test-environment">Test Environment</h3>
<ul>
<li>Environment variables are loaded from <code>.env.test</code>.</li>
<li>Console output is minimized unless <code>DEBUG=true</code>.</li>
<li>JWT secrets and tokens are preconfigured for testing.</li>
<li>Rate limiting and security features are initialized appropriately.</li>
</ul>
<h2 id="running-tests">Running Tests</h2>
<div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="c1"># Basic test run</span>
<a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a>bun<span class="w"> </span><span class="nb">test</span>
<a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a>
<a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="c1"># Run tests with coverage</span>
<a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage
<a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a>
<a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="c1"># Run a specific test file</span>
<a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>path/to/test.test.ts
<a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a>
<a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a><span class="c1"># Run tests in watch mode</span>
<a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--watch
<a id="__codelineno-5-12" name="__codelineno-5-12" href="#__codelineno-5-12"></a>
<a id="__codelineno-5-13" name="__codelineno-5-13" href="#__codelineno-5-13"></a><span class="c1"># Run tests with debug output</span>
<a id="__codelineno-5-14" name="__codelineno-5-14" href="#__codelineno-5-14"></a><span class="nv">DEBUG</span><span class="o">=</span><span class="nb">true</span><span class="w"> </span>bun<span class="w"> </span><span class="nb">test</span>
<a id="__codelineno-5-15" name="__codelineno-5-15" href="#__codelineno-5-15"></a>
<a id="__codelineno-5-16" name="__codelineno-5-16" href="#__codelineno-5-16"></a><span class="c1"># Run tests with increased timeout</span>
<a id="__codelineno-5-17" name="__codelineno-5-17" href="#__codelineno-5-17"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--timeout<span class="w"> </span><span class="m">60000</span>
<a id="__codelineno-5-18" name="__codelineno-5-18" href="#__codelineno-5-18"></a>
<a id="__codelineno-5-19" name="__codelineno-5-19" href="#__codelineno-5-19"></a><span class="c1"># Run tests matching a pattern</span>
<a id="__codelineno-5-20" name="__codelineno-5-20" href="#__codelineno-5-20"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--pattern<span class="w"> </span><span class="s2">&quot;auth&quot;</span>
</code></pre></div>
<h2 id="advanced-debugging">Advanced Debugging</h2>
<h3 id="using-node-inspector">Using Node Inspector</h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a><span class="c1"># Start tests with inspector</span>
<a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--inspect
<a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a>
<a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a><span class="c1"># Start tests with inspector and break on first line</span>
<a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--inspect-brk
</code></pre></div>
<h3 id="using-vs-code">Using VS Code</h3>
<p>Create a launch configuration in <code>.vscode/launch.json</code>:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-7-1" name="__codelineno-7-1" href="#__codelineno-7-1"></a><span class="p">{</span>
<a id="__codelineno-7-2" name="__codelineno-7-2" href="#__codelineno-7-2"></a><span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.2.0&quot;</span><span class="p">,</span>
<a id="__codelineno-7-3" name="__codelineno-7-3" href="#__codelineno-7-3"></a><span class="w"> </span><span class="nt">&quot;configurations&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<a id="__codelineno-7-4" name="__codelineno-7-4" href="#__codelineno-7-4"></a><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-7-5" name="__codelineno-7-5" href="#__codelineno-7-5"></a><span class="w"> </span><span class="nt">&quot;type&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;bun&quot;</span><span class="p">,</span>
<a id="__codelineno-7-6" name="__codelineno-7-6" href="#__codelineno-7-6"></a><span class="w"> </span><span class="nt">&quot;request&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;launch&quot;</span><span class="p">,</span>
<a id="__codelineno-7-7" name="__codelineno-7-7" href="#__codelineno-7-7"></a><span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;Debug Tests&quot;</span><span class="p">,</span>
<a id="__codelineno-7-8" name="__codelineno-7-8" href="#__codelineno-7-8"></a><span class="w"> </span><span class="nt">&quot;program&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;${workspaceFolder}/node_modules/bun/bin/bun&quot;</span><span class="p">,</span>
<a id="__codelineno-7-9" name="__codelineno-7-9" href="#__codelineno-7-9"></a><span class="w"> </span><span class="nt">&quot;args&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;test&quot;</span><span class="p">,</span><span class="w"> </span><span class="s2">&quot;${file}&quot;</span><span class="p">],</span>
<a id="__codelineno-7-10" name="__codelineno-7-10" href="#__codelineno-7-10"></a><span class="w"> </span><span class="nt">&quot;cwd&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;${workspaceFolder}&quot;</span><span class="p">,</span>
<a id="__codelineno-7-11" name="__codelineno-7-11" href="#__codelineno-7-11"></a><span class="w"> </span><span class="nt">&quot;env&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nt">&quot;DEBUG&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;true&quot;</span><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-12" name="__codelineno-7-12" href="#__codelineno-7-12"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-7-13" name="__codelineno-7-13" href="#__codelineno-7-13"></a><span class="w"> </span><span class="p">]</span>
<a id="__codelineno-7-14" name="__codelineno-7-14" href="#__codelineno-7-14"></a><span class="p">}</span>
</code></pre></div>
<h3 id="test-isolation">Test Isolation</h3>
<p>To run a single test in isolation:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-8-1" name="__codelineno-8-1" href="#__codelineno-8-1"></a><span class="nx">describe</span><span class="p">.</span><span class="nx">only</span><span class="p">(</span><span class="s2">&quot;specific test suite&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-8-2" name="__codelineno-8-2" href="#__codelineno-8-2"></a><span class="w"> </span><span class="nx">it</span><span class="p">.</span><span class="nx">only</span><span class="p">(</span><span class="s2">&quot;specific test case&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-8-3" name="__codelineno-8-3" href="#__codelineno-8-3"></a><span class="w"> </span><span class="c1">// Only this test will run</span>
<a id="__codelineno-8-4" name="__codelineno-8-4" href="#__codelineno-8-4"></a><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-8-5" name="__codelineno-8-5" href="#__codelineno-8-5"></a><span class="p">});</span>
</code></pre></div>
<h2 id="writing-tests">Writing Tests</h2>
<h3 id="test-file-naming">Test File Naming</h3>
<ul>
<li>Place test files in a <code>__tests__</code> directory adjacent to the code being tested.</li>
<li>Name files with the pattern <code>*.test.ts</code>.</li>
<li>Mirror the structure of the source code in your test organization.</li>
</ul>
<h3 id="example-test-structure">Example Test Structure</h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-9-1" name="__codelineno-9-1" href="#__codelineno-9-1"></a><span class="nx">describe</span><span class="p">(</span><span class="s2">&quot;Security Features&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-2" name="__codelineno-9-2" href="#__codelineno-9-2"></a><span class="w"> </span><span class="nx">it</span><span class="p">(</span><span class="s2">&quot;should validate tokens correctly&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-9-3" name="__codelineno-9-3" href="#__codelineno-9-3"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">payload</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">userId</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;123&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">role</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;user&quot;</span><span class="w"> </span><span class="p">};</span>
<a id="__codelineno-9-4" name="__codelineno-9-4" href="#__codelineno-9-4"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">token</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">jwt</span><span class="p">.</span><span class="nx">sign</span><span class="p">(</span><span class="nx">payload</span><span class="p">,</span><span class="w"> </span><span class="nx">validSecret</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">expiresIn</span><span class="o">:</span><span class="w"> </span><span class="s2">&quot;1h&quot;</span><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-9-5" name="__codelineno-9-5" href="#__codelineno-9-5"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TokenManager</span><span class="p">.</span><span class="nx">validateToken</span><span class="p">(</span><span class="nx">token</span><span class="p">,</span><span class="w"> </span><span class="nx">testIp</span><span class="p">);</span>
<a id="__codelineno-9-6" name="__codelineno-9-6" href="#__codelineno-9-6"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">valid</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<a id="__codelineno-9-7" name="__codelineno-9-7" href="#__codelineno-9-7"></a><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-9-8" name="__codelineno-9-8" href="#__codelineno-9-8"></a><span class="p">});</span>
</code></pre></div>
<h2 id="coverage">Coverage</h2>
<p>The project maintains strict coverage:
- Overall coverage: at least 80%
- Critical paths: 90%+
- New features: ≥85% coverage</p>
<p>Generate a coverage report with:</p>
<div class="highlight"><pre><span></span><code><a id="__codelineno-10-1" name="__codelineno-10-1" href="#__codelineno-10-1"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage
</code></pre></div>
<h2 id="security-middleware-testing">Security Middleware Testing</h2>
<h3 id="utility-function-testing">Utility Function Testing</h3>
<p>The security middleware now uses a utility-first approach, which allows for more granular and comprehensive testing. Each security function is now independently testable, improving code reliability and maintainability.</p>
<h4 id="key-utility-functions">Key Utility Functions</h4>
<ol>
<li><strong>Rate Limiting (<code>checkRateLimit</code>)</strong></li>
<li>Tests multiple scenarios:<ul>
<li>Requests under threshold</li>
<li>Requests exceeding threshold</li>
<li>Rate limit reset after window expiration</li>
</ul>
</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-11-1" name="__codelineno-11-1" href="#__codelineno-11-1"></a><span class="c1">// Example test</span>
<a id="__codelineno-11-2" name="__codelineno-11-2" href="#__codelineno-11-2"></a><span class="nx">it</span><span class="p">(</span><span class="s1">&#39;should throw when requests exceed threshold&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-11-3" name="__codelineno-11-3" href="#__codelineno-11-3"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">ip</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;127.0.0.2&#39;</span><span class="p">;</span>
<a id="__codelineno-11-4" name="__codelineno-11-4" href="#__codelineno-11-4"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mf">11</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-11-5" name="__codelineno-11-5" href="#__codelineno-11-5"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mf">10</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-11-6" name="__codelineno-11-6" href="#__codelineno-11-6"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">checkRateLimit</span><span class="p">(</span><span class="nx">ip</span><span class="p">,</span><span class="w"> </span><span class="mf">10</span><span class="p">)).</span><span class="nx">not</span><span class="p">.</span><span class="nx">toThrow</span><span class="p">();</span>
<a id="__codelineno-11-7" name="__codelineno-11-7" href="#__codelineno-11-7"></a><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-11-8" name="__codelineno-11-8" href="#__codelineno-11-8"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">checkRateLimit</span><span class="p">(</span><span class="nx">ip</span><span class="p">,</span><span class="w"> </span><span class="mf">10</span><span class="p">)).</span><span class="nx">toThrow</span><span class="p">(</span><span class="s1">&#39;Too many requests from this IP&#39;</span><span class="p">);</span>
<a id="__codelineno-11-9" name="__codelineno-11-9" href="#__codelineno-11-9"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-11-10" name="__codelineno-11-10" href="#__codelineno-11-10"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-11-11" name="__codelineno-11-11" href="#__codelineno-11-11"></a><span class="p">});</span>
</code></pre></div>
<ol>
<li><strong>Request Validation (<code>validateRequestHeaders</code>)</strong></li>
<li>Tests content type validation</li>
<li>Checks request size limits</li>
<li>Validates authorization headers</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-12-1" name="__codelineno-12-1" href="#__codelineno-12-1"></a><span class="nx">it</span><span class="p">(</span><span class="s1">&#39;should reject invalid content type&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-12-2" name="__codelineno-12-2" href="#__codelineno-12-2"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">mockRequest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Request</span><span class="p">(</span><span class="s1">&#39;http://localhost&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-12-3" name="__codelineno-12-3" href="#__codelineno-12-3"></a><span class="w"> </span><span class="nx">method</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;POST&#39;</span><span class="p">,</span>
<a id="__codelineno-12-4" name="__codelineno-12-4" href="#__codelineno-12-4"></a><span class="w"> </span><span class="nx">headers</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s1">&#39;content-type&#39;</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;text/plain&#39;</span><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-12-5" name="__codelineno-12-5" href="#__codelineno-12-5"></a><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-12-6" name="__codelineno-12-6" href="#__codelineno-12-6"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">validateRequestHeaders</span><span class="p">(</span><span class="nx">mockRequest</span><span class="p">)).</span><span class="nx">toThrow</span><span class="p">(</span><span class="s1">&#39;Content-Type must be application/json&#39;</span><span class="p">);</span>
<a id="__codelineno-12-7" name="__codelineno-12-7" href="#__codelineno-12-7"></a><span class="p">});</span>
</code></pre></div>
<ol>
<li><strong>Input Sanitization (<code>sanitizeValue</code>)</strong></li>
<li>Sanitizes HTML tags</li>
<li>Handles nested objects</li>
<li>Preserves non-string values</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-13-1" name="__codelineno-13-1" href="#__codelineno-13-1"></a><span class="nx">it</span><span class="p">(</span><span class="s1">&#39;should sanitize HTML tags&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-13-2" name="__codelineno-13-2" href="#__codelineno-13-2"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">input</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">&#39;&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;Hello&#39;</span><span class="p">;</span>
<a id="__codelineno-13-3" name="__codelineno-13-3" href="#__codelineno-13-3"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">sanitized</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">sanitizeValue</span><span class="p">(</span><span class="nx">input</span><span class="p">);</span>
<a id="__codelineno-13-4" name="__codelineno-13-4" href="#__codelineno-13-4"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(</span><span class="nx">sanitized</span><span class="p">).</span><span class="nx">toBe</span><span class="p">(</span><span class="s1">&#39;&amp;lt;script&amp;gt;alert(&amp;quot;xss&amp;quot;)&amp;lt;/script&amp;gt;Hello&#39;</span><span class="p">);</span>
<a id="__codelineno-13-5" name="__codelineno-13-5" href="#__codelineno-13-5"></a><span class="p">});</span>
</code></pre></div>
<ol>
<li><strong>Security Headers (<code>applySecurityHeaders</code>)</strong></li>
<li>Verifies correct security header application</li>
<li>Checks CSP, frame options, and other security headers</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-14-1" name="__codelineno-14-1" href="#__codelineno-14-1"></a><span class="nx">it</span><span class="p">(</span><span class="s1">&#39;should apply security headers&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-14-2" name="__codelineno-14-2" href="#__codelineno-14-2"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">mockRequest</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Request</span><span class="p">(</span><span class="s1">&#39;http://localhost&#39;</span><span class="p">);</span>
<a id="__codelineno-14-3" name="__codelineno-14-3" href="#__codelineno-14-3"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">headers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">applySecurityHeaders</span><span class="p">(</span><span class="nx">mockRequest</span><span class="p">);</span>
<a id="__codelineno-14-4" name="__codelineno-14-4" href="#__codelineno-14-4"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(</span><span class="nx">headers</span><span class="p">[</span><span class="s1">&#39;content-security-policy&#39;</span><span class="p">]).</span><span class="nx">toBeDefined</span><span class="p">();</span>
<a id="__codelineno-14-5" name="__codelineno-14-5" href="#__codelineno-14-5"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(</span><span class="nx">headers</span><span class="p">[</span><span class="s1">&#39;x-frame-options&#39;</span><span class="p">]).</span><span class="nx">toBeDefined</span><span class="p">();</span>
<a id="__codelineno-14-6" name="__codelineno-14-6" href="#__codelineno-14-6"></a><span class="p">});</span>
</code></pre></div>
<ol>
<li><strong>Error Handling (<code>handleError</code>)</strong></li>
<li>Tests error responses in production and development modes</li>
<li>Verifies error message and stack trace inclusion</li>
</ol>
<div class="highlight"><pre><span></span><code><a id="__codelineno-15-1" name="__codelineno-15-1" href="#__codelineno-15-1"></a><span class="nx">it</span><span class="p">(</span><span class="s1">&#39;should include error details in development mode&#39;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-15-2" name="__codelineno-15-2" href="#__codelineno-15-2"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">error</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s1">&#39;Test error&#39;</span><span class="p">);</span>
<a id="__codelineno-15-3" name="__codelineno-15-3" href="#__codelineno-15-3"></a><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">handleError</span><span class="p">(</span><span class="nx">error</span><span class="p">,</span><span class="w"> </span><span class="s1">&#39;development&#39;</span><span class="p">);</span>
<a id="__codelineno-15-4" name="__codelineno-15-4" href="#__codelineno-15-4"></a><span class="w"> </span><span class="nx">expect</span><span class="p">(</span><span class="nx">result</span><span class="p">).</span><span class="nx">toEqual</span><span class="p">({</span>
<a id="__codelineno-15-5" name="__codelineno-15-5" href="#__codelineno-15-5"></a><span class="w"> </span><span class="nx">error</span><span class="o">:</span><span class="w"> </span><span class="kt">true</span><span class="p">,</span>
<a id="__codelineno-15-6" name="__codelineno-15-6" href="#__codelineno-15-6"></a><span class="w"> </span><span class="nx">message</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;Internal server error&#39;</span><span class="p">,</span>
<a id="__codelineno-15-7" name="__codelineno-15-7" href="#__codelineno-15-7"></a><span class="w"> </span><span class="nx">error</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;Test error&#39;</span><span class="p">,</span>
<a id="__codelineno-15-8" name="__codelineno-15-8" href="#__codelineno-15-8"></a><span class="w"> </span><span class="nx">stack</span><span class="o">:</span><span class="w"> </span><span class="kt">expect.any</span><span class="p">(</span><span class="nb">String</span><span class="p">)</span>
<a id="__codelineno-15-9" name="__codelineno-15-9" href="#__codelineno-15-9"></a><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-15-10" name="__codelineno-15-10" href="#__codelineno-15-10"></a><span class="p">});</span>
</code></pre></div>
<h3 id="testing-philosophy">Testing Philosophy</h3>
<ul>
<li><strong>Isolation</strong>: Each utility function is tested independently</li>
<li><strong>Comprehensive Coverage</strong>: Multiple scenarios for each function</li>
<li><strong>Predictable Behavior</strong>: Clear expectations for input and output</li>
<li><strong>Error Handling</strong>: Robust testing of error conditions</li>
</ul>
<h3 id="best-practices">Best Practices</h3>
<ol>
<li>Use minimal, focused test cases</li>
<li>Test both successful and failure scenarios</li>
<li>Verify input sanitization and security measures</li>
<li>Mock external dependencies when necessary</li>
</ol>
<h3 id="running-security-tests">Running Security Tests</h3>
<div class="highlight"><pre><span></span><code><a id="__codelineno-16-1" name="__codelineno-16-1" href="#__codelineno-16-1"></a><span class="c1"># Run all tests</span>
<a id="__codelineno-16-2" name="__codelineno-16-2" href="#__codelineno-16-2"></a>bun<span class="w"> </span><span class="nb">test</span>
<a id="__codelineno-16-3" name="__codelineno-16-3" href="#__codelineno-16-3"></a>
<a id="__codelineno-16-4" name="__codelineno-16-4" href="#__codelineno-16-4"></a><span class="c1"># Run specific security tests</span>
<a id="__codelineno-16-5" name="__codelineno-16-5" href="#__codelineno-16-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>__tests__/security/
</code></pre></div>
<h3 id="continuous-improvement">Continuous Improvement</h3>
<ul>
<li>Regularly update test cases</li>
<li>Add new test scenarios as security requirements evolve</li>
<li>Perform periodic security audits</li>
</ul>
<h2 id="best-practices_1">Best Practices</h2>
<ol>
<li><strong>Isolation</strong>: Each test should be independent and not rely on the state of other tests.</li>
<li><strong>Mocking</strong>: Use the provided mock utilities for external dependencies.</li>
<li><strong>Cleanup</strong>: Clean up any resources or state modifications in <code>afterEach</code> or <code>afterAll</code> hooks.</li>
<li><strong>Descriptive Names</strong>: Use clear, descriptive test names that explain the expected behavior.</li>
<li><strong>Assertions</strong>: Make specific, meaningful assertions rather than general ones.</li>
<li><strong>Setup</strong>: Use <code>beforeEach</code> for common test setup to avoid repetition.</li>
<li><strong>Error Cases</strong>: Test both success and error cases for complete coverage.</li>
</ol>
<h2 id="coverage_1">Coverage</h2>
<p>The project aims for high test coverage, particularly focusing on:
- Security-critical code paths
- API endpoints
- Data validation
- Error handling
- Event broadcasting</p>
<p>Run coverage reports using:
<div class="highlight"><pre><span></span><code><a id="__codelineno-17-1" name="__codelineno-17-1" href="#__codelineno-17-1"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage
</code></pre></div></p>
<h2 id="debugging-tests">Debugging Tests</h2>
<p>To debug tests:
1. Set <code>DEBUG=true</code> to enable console output during tests
2. Use the <code>--watch</code> flag for development
3. Add <code>console.log()</code> statements (they're only shown when DEBUG is true)
4. Use the test utilities' debugging helpers</p>
<h3 id="advanced-debugging_1">Advanced Debugging</h3>
<ol>
<li>
<p><strong>Using Node Inspector</strong>:
<div class="highlight"><pre><span></span><code><a id="__codelineno-18-1" name="__codelineno-18-1" href="#__codelineno-18-1"></a><span class="c1"># Start tests with inspector</span>
<a id="__codelineno-18-2" name="__codelineno-18-2" href="#__codelineno-18-2"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--inspect
<a id="__codelineno-18-3" name="__codelineno-18-3" href="#__codelineno-18-3"></a>
<a id="__codelineno-18-4" name="__codelineno-18-4" href="#__codelineno-18-4"></a><span class="c1"># Start tests with inspector and break on first line</span>
<a id="__codelineno-18-5" name="__codelineno-18-5" href="#__codelineno-18-5"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--inspect-brk
</code></pre></div></p>
</li>
<li>
<p><strong>Using VS Code</strong>:
<div class="highlight"><pre><span></span><code><a id="__codelineno-19-1" name="__codelineno-19-1" href="#__codelineno-19-1"></a>// .vscode/launch.json
<a id="__codelineno-19-2" name="__codelineno-19-2" href="#__codelineno-19-2"></a>{
<a id="__codelineno-19-3" name="__codelineno-19-3" href="#__codelineno-19-3"></a> &quot;version&quot;: &quot;0.2.0&quot;,
<a id="__codelineno-19-4" name="__codelineno-19-4" href="#__codelineno-19-4"></a> &quot;configurations&quot;: [
<a id="__codelineno-19-5" name="__codelineno-19-5" href="#__codelineno-19-5"></a> {
<a id="__codelineno-19-6" name="__codelineno-19-6" href="#__codelineno-19-6"></a> &quot;type&quot;: &quot;bun&quot;,
<a id="__codelineno-19-7" name="__codelineno-19-7" href="#__codelineno-19-7"></a> &quot;request&quot;: &quot;launch&quot;,
<a id="__codelineno-19-8" name="__codelineno-19-8" href="#__codelineno-19-8"></a> &quot;name&quot;: &quot;Debug Tests&quot;,
<a id="__codelineno-19-9" name="__codelineno-19-9" href="#__codelineno-19-9"></a> &quot;program&quot;: &quot;${workspaceFolder}/node_modules/bun/bin/bun&quot;,
<a id="__codelineno-19-10" name="__codelineno-19-10" href="#__codelineno-19-10"></a> &quot;args&quot;: [&quot;test&quot;, &quot;${file}&quot;],
<a id="__codelineno-19-11" name="__codelineno-19-11" href="#__codelineno-19-11"></a> &quot;cwd&quot;: &quot;${workspaceFolder}&quot;,
<a id="__codelineno-19-12" name="__codelineno-19-12" href="#__codelineno-19-12"></a> &quot;env&quot;: { &quot;DEBUG&quot;: &quot;true&quot; }
<a id="__codelineno-19-13" name="__codelineno-19-13" href="#__codelineno-19-13"></a> }
<a id="__codelineno-19-14" name="__codelineno-19-14" href="#__codelineno-19-14"></a> ]
<a id="__codelineno-19-15" name="__codelineno-19-15" href="#__codelineno-19-15"></a>}
</code></pre></div></p>
</li>
<li>
<p><strong>Test Isolation</strong>:
To run a single test in isolation:
<div class="highlight"><pre><span></span><code><a id="__codelineno-20-1" name="__codelineno-20-1" href="#__codelineno-20-1"></a><span class="nx">describe</span><span class="p">.</span><span class="nx">only</span><span class="p">(</span><span class="s2">&quot;specific test suite&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-20-2" name="__codelineno-20-2" href="#__codelineno-20-2"></a><span class="w"> </span><span class="nx">it</span><span class="p">.</span><span class="nx">only</span><span class="p">(</span><span class="s2">&quot;specific test case&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-20-3" name="__codelineno-20-3" href="#__codelineno-20-3"></a><span class="w"> </span><span class="c1">// Only this test will run</span>
<a id="__codelineno-20-4" name="__codelineno-20-4" href="#__codelineno-20-4"></a><span class="w"> </span><span class="p">});</span>
<a id="__codelineno-20-5" name="__codelineno-20-5" href="#__codelineno-20-5"></a><span class="p">});</span>
</code></pre></div></p>
</li>
</ol>
<h2 id="contributing">Contributing</h2>
<p>When contributing new code:
1. Add tests for new features
2. Ensure existing tests pass
3. Maintain or improve coverage
4. Follow the existing test patterns and naming conventions
5. Document any new test utilities or patterns </p>
<h2 id="coverage-requirements">Coverage Requirements</h2>
<p>The project maintains strict coverage requirements:</p>
<ul>
<li>Minimum overall coverage: 80%</li>
<li>Critical paths (security, API, data validation): 90%</li>
<li>New features must include tests with &gt;= 85% coverage</li>
</ul>
<p>Coverage reports are generated in multiple formats:
- Console summary
- HTML report (./coverage/index.html)
- LCOV report (./coverage/lcov.info)</p>
<p>To view detailed coverage:
<div class="highlight"><pre><span></span><code><a id="__codelineno-21-1" name="__codelineno-21-1" href="#__codelineno-21-1"></a><span class="c1"># Generate and open coverage report</span>
<a id="__codelineno-21-2" name="__codelineno-21-2" href="#__codelineno-21-2"></a>bun<span class="w"> </span><span class="nb">test</span><span class="w"> </span>--coverage<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>open<span class="w"> </span>coverage/index.html
</code></pre></div></p>
<aside class="md-source-file">
<span class="md-source-file__fact">
<span class="md-icon" title="Last update">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg>
</span>
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">February 5, 2025</span>
</span>
</aside>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright &copy; 2025 jango-blockchained
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://github.com/jango-blockchained/homeassistant-mcp" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg>
</a>
<a href="https://hub.docker.com/r/jangoblockchained/homeassistant-mcp" target="_blank" rel="noopener" title="hub.docker.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M349.9 236.3h-66.1v-59.4h66.1zm0-204.3h-66.1v60.7h66.1zm78.2 144.8H362v59.4h66.1zm-156.3-72.1h-66.1v60.1h66.1zm78.1 0h-66.1v60.1h66.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1zm78.1 0h-66.1v59.4h66.1zm-78.1-72.1h-66.1v60.1h66.1z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "..", "features": ["navigation.instant", "navigation.tracking", "navigation.sections", "navigation.expand", "navigation.top", "search.suggest", "search.highlight", "content.code.copy"], "search": "../assets/javascripts/workers/search.f8cc74c7.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
<script src="../assets/javascripts/bundle.f13b1293.min.js"></script>
<script src="../javascripts/extra.js"></script>
</body>
</html>