An open API service indexing awesome lists of open source software.

https://github.com/luontola/html-utils

Utilities for writing and testing HTML on Node.js
https://github.com/luontola/html-utils

html html-templating htmx javascript javascript-library nodejs react testing-tools typescript

Last synced: over 1 year ago
JSON representation

Utilities for writing and testing HTML on Node.js

Awesome Lists containing this project

README

          

# Esko's HTML Utils

This project contains a couple utilities for writing and testing HTML in JavaScript/Node.js.

These utilities are not available on npm, but they are meant to be copy-pasted into your project. They come complete
with unit tests, so they can be evolved to fit your project's needs.

## HTML Templating

There is a tag function for writing tagged templates, to produce HTML without a heavy framework like React.

The placeholders are automatically escaped to avoid XSS vulnerabilities.

```js
const input = "alert(1)"
const output = html`

Hello ${input}

`
expect(output.html).toBe("

Hello <script>alert(1)</script>

")
```

You can create components using plain old functions. Works great with [htmx](https://htmx.org/).

```js
function homePage() {
return html`

Welcome


${clickerButton()}


`
}

function clickerButton(counter: number = 0) {
return html`

Clicked ${counter} times

`
}
```

See [html-templates.ts](src/html-templates.ts) and [html-templates.test.ts](test/html-templates.test.ts)

## Unit Testing the UI

There is a helper function for extracting the visible text from HTML, to easily unit test HTML templates.

The components mentioned in the previous section could be unit tested like this:

```js
expect(visualizeHtml(homePage())).toBe(normalizeWhitespace(`
Welcome
Clicked 0 times`))

const button = clickerButton(5)
expect(visualizeHtml(button)).toBe("Clicked 5 times")
expect(button.html).toContain(`hx-get="/clicker?counter=6"`)
```

By default `visualizeHtml` strips all HTML tags.
But if you add a `data-test-icon` attribute to an element, the element will be replaced with its value.
This enables [stringly asserted](https://martinfowler.com/articles/tdd-html-templates.html#BonusLevelStringlyAsserted)
testing to assert non-textual information.

```js
expect(visualizeHtml("

one

two

")).toBe("one two")
expect(visualizeHtml(``)).toBe("☑️")
```

In addition to raw HTML and [our HTML templates](#html-templating), `visualizeHtml` works also for React elements.
If you use only one of them, you can delete a few lines from `visualizeHtml` to remove the unnecessary dependency.

See [html-testing.ts](src/html-testing.ts) and [html-testing.test.ts](test/html-testing.test.ts)

## Installing

To use this library, download it to be part of your project:

```
wget https://raw.githubusercontent.com/luontola/html-utils/refs/heads/main/src/html-templates.ts
wget https://raw.githubusercontent.com/luontola/html-utils/refs/heads/main/test/html-templates.test.ts
wget https://raw.githubusercontent.com/luontola/html-utils/refs/heads/main/src/html-testing.ts
wget https://raw.githubusercontent.com/luontola/html-utils/refs/heads/main/test/html-testing.test.ts
```

In particular, the testing library often benefits from project-specific customizations.

This library is [finished software](https://josem.co/the-beauty-of-finished-software/), so there is no need to get
constant updates to it.
No new features is a feature in itself.
You wouldn't want to be [left-padded](https://en.wikipedia.org/wiki/Npm_left-pad_incident) because of just 50 lines of
code, would you?