generated from coulomb/repo-seed
199 lines
8.3 KiB
Markdown
199 lines
8.3 KiB
Markdown
# 🧪 Introduction to Test-Driven-UI Development
|
||
|
||
Here’s an introduction to the **TestDrive-UI development philosophy**.
|
||
|
||
It explains *how to develop UI components the TestDrive-UI way*, why each tool is part of the stack, and links directly to their official projects.
|
||
|
||
---
|
||
|
||
### “Design the test first — let the interface emerge”
|
||
|
||
---
|
||
|
||
## 🎯 What is TestDrive-UI?
|
||
|
||
**TestDrive-UI** is a lightweight, browser-first development scaffold for building interactive web components using a **Test-Driven Development (TDD)** workflow.
|
||
|
||
It provides a reproducible structure that’s simple enough for hobby projects, but robust enough for AI-assisted, agent-driven development loops.
|
||
|
||
> **Core idea:**
|
||
> Every UI feature begins as a **behavioral test** — not a design or mockup.
|
||
> The implementation grows only to satisfy that test.
|
||
> The UI emerges naturally from verified expectations.
|
||
|
||
---
|
||
|
||
## 🧱 The Toolchain Overview
|
||
|
||
| Tool | Purpose | Why it’s used | Website |
|
||
| -------------------------------------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||
| 🧩 **[Lit](https://lit.dev/)** | Define Web Components with declarative rendering | Fast, framework-agnostic, minimal build overhead; lets you create reusable, encapsulated components | [https://lit.dev](https://lit.dev) |
|
||
| 🧪 **[Mocha](https://mochajs.org/)** | Test runner for JavaScript | Mature, flexible, CLI-friendly — ideal for writing descriptive, behavior-oriented tests (`describe` / `it`) | [https://mochajs.org](https://mochajs.org) |
|
||
| 💬 **[Chai](https://www.chaijs.com/)** | Assertion library | Clean, readable syntax for expectations (`expect(value).to.equal(...)`) | [https://www.chaijs.com](https://www.chaijs.com) |
|
||
| 🧠 **[JSDOM](https://github.com/jsdom/jsdom)** | Simulated DOM for Node | Lets you run DOM-based UI tests without a browser; deterministic and CI-friendly | [https://github.com/jsdom/jsdom](https://github.com/jsdom/jsdom) |
|
||
| ⚡ **[Vite](https://vitejs.dev/)** | Development server & bundler | Instant hot-reloads and minimal config for web-component projects | [https://vitejs.dev](https://vitejs.dev) |
|
||
| 🧱 **[Storybook](https://storybook.js.org/)** (optional) | Visual component sandbox | Lets you document, preview, and visually test each component in isolation | [https://storybook.js.org](https://storybook.js.org) |
|
||
| 🔬 **[Playwright](https://playwright.dev/)** (optional) | End-to-end browser testing | Adds full browser automation for real UI validation | [https://playwright.dev](https://playwright.dev) |
|
||
|
||
Together, these tools form the **TestDrive-UI loop**:
|
||
|
||
```
|
||
Requirement → Test (Mocha+Chai) → Implementation (Lit) → Run (Vite) → Refine → Repeat
|
||
```
|
||
|
||
---
|
||
|
||
## 🧩 How the Development Flow Works
|
||
|
||
### 1. Define the Behavior
|
||
|
||
Write a short **requirement statement** or JSON spec describing what the component *should do* — not how it looks.
|
||
|
||
Example:
|
||
|
||
> “When the user types in the input field, the greeting updates immediately.”
|
||
|
||
This requirement drives both test and implementation.
|
||
|
||
---
|
||
|
||
### 2. Write the Test First
|
||
|
||
Create a Mocha test file in `src/components/<component-name>/<component>.test.js`:
|
||
|
||
```javascript
|
||
import "./hello-world.js";
|
||
|
||
describe("<hello-world>", () => {
|
||
it("updates the greeting when user types", async () => {
|
||
const el = document.createElement("hello-world");
|
||
document.body.appendChild(el);
|
||
const input = el.shadowRoot.querySelector("input");
|
||
input.value = "Agent";
|
||
input.dispatchEvent(new Event("input"));
|
||
await el.updateComplete;
|
||
const greeting = el.shadowRoot.querySelector(".greeting");
|
||
expect(greeting.textContent.trim()).to.equal("Hello, Agent!");
|
||
});
|
||
});
|
||
```
|
||
|
||
When you run `npm test`, this test will **fail** until you implement the behavior.
|
||
|
||
---
|
||
|
||
### 3. Implement Just Enough Code to Pass
|
||
|
||
Write the smallest possible component in **Lit** to satisfy the test:
|
||
|
||
```javascript
|
||
import { LitElement, html, css } from "lit";
|
||
|
||
export class HelloWorld extends LitElement {
|
||
static properties = { name: { type: String } };
|
||
constructor() { super(); this.name = "World"; }
|
||
|
||
render() {
|
||
return html`
|
||
<div class="greeting">Hello, ${this.name}!</div>
|
||
<input type="text" .value=${this.name} @input=${this._onInput} />
|
||
`;
|
||
}
|
||
_onInput(e) { this.name = e.target.value; }
|
||
}
|
||
customElements.define("hello-world", HelloWorld);
|
||
```
|
||
|
||
Run tests again — they should now pass.
|
||
|
||
---
|
||
|
||
### 4. Refine, Extend, and Visualize
|
||
|
||
When a component works, visualize it:
|
||
|
||
```bash
|
||
npm run dev
|
||
```
|
||
|
||
Vite opens the browser instantly so you can adjust styling and layout.
|
||
|
||
Optionally, use Storybook to display multiple variants:
|
||
|
||
```javascript
|
||
export default { title: "UI/Hello World" };
|
||
export const Default = () => `<hello-world></hello-world>`;
|
||
export const Named = () => `<hello-world name="Coulomb"></hello-world>`;
|
||
```
|
||
|
||
---
|
||
|
||
### 5. Iterate
|
||
|
||
Each new behavior (feature, bugfix, style rule, accessibility improvement) starts with a **new test**.
|
||
The system evolves incrementally, each step verifiable by automation.
|
||
|
||
---
|
||
|
||
## 🧠 Why This Matters
|
||
|
||
| Principle | Benefit |
|
||
| ----------------------------------------- | ------------------------------------------------ |
|
||
| **TDD-first** | Prevents UI drift and regression early. |
|
||
| **Declarative UI (Lit)** | Clean separation of state and template. |
|
||
| **Deterministic Testing (JSDOM + Mocha)** | Reproducible results without browser complexity. |
|
||
| **Fast Iteration (Vite)** | Keeps flow tight and interactive. |
|
||
| **Optional Visual Layer (Storybook)** | Communication and design documentation built in. |
|
||
|
||
---
|
||
|
||
## 🧩 Advanced Extensions
|
||
|
||
Once the base workflow feels solid, TestDrive-UI scales elegantly to more advanced cases:
|
||
|
||
* **Shared reactive stores** — implement central state management (see Tutorial 6).
|
||
* **Persistence** — save data using localStorage or IndexedDB (see Tutorial 7).
|
||
* **Agent automation** — use AI coding agents to generate and maintain tests automatically (see Tutorial 8).
|
||
* **End-to-end testing** — run full browser simulations via Playwright.
|
||
|
||
---
|
||
|
||
## 🔗 Official Tool Links
|
||
|
||
| Tool | Website |
|
||
| ---------- | ---------------------------------------------------------------- |
|
||
| Lit | [https://lit.dev](https://lit.dev) |
|
||
| Mocha | [https://mochajs.org](https://mochajs.org) |
|
||
| Chai | [https://www.chaijs.com](https://www.chaijs.com) |
|
||
| JSDOM | [https://github.com/jsdom/jsdom](https://github.com/jsdom/jsdom) |
|
||
| Vite | [https://vitejs.dev](https://vitejs.dev) |
|
||
| Storybook | [https://storybook.js.org](https://storybook.js.org) |
|
||
| Playwright | [https://playwright.dev](https://playwright.dev) |
|
||
|
||
---
|
||
|
||
## 🚀 Quick Start Recap
|
||
|
||
```bash
|
||
# Clone or unzip scaffold
|
||
npm install
|
||
|
||
# Run tests
|
||
npm test
|
||
|
||
# Start live preview
|
||
npm run dev
|
||
```
|
||
|
||
* Tests define behavior.
|
||
* Components evolve from tests.
|
||
* UIs emerge naturally from verified code.
|
||
|
||
> **TestDrive-UI** isn’t a framework — it’s a *method*.
|
||
> It’s how you and your coding agents learn to reason about interfaces through evidence.
|
||
|
||
---
|
||
|
||
Start with our tutorials to get going.
|
||
|
||
xxx |