{"id":46233694,"url":"https://github.com/htest-dev/htest-html","last_synced_at":"2026-03-03T18:14:08.805Z","repository":{"id":286110985,"uuid":"950536640","full_name":"htest-dev/htest-html","owner":"htest-dev","description":"Write tests in HTML, with reactive evaluation and mock interactions!","archived":false,"fork":false,"pushed_at":"2025-04-04T11:21:23.000Z","size":108,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-04T12:25:45.753Z","etag":null,"topics":["testing","unit-testing"],"latest_commit_sha":null,"homepage":"https://html.htest.dev","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/htest-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-03-18T10:10:42.000Z","updated_at":"2025-04-04T11:19:59.000Z","dependencies_parsed_at":"2025-04-04T12:36:06.312Z","dependency_job_id":null,"html_url":"https://github.com/htest-dev/htest-html","commit_stats":null,"previous_names":["htest-dev/htest-html"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/htest-dev/htest-html","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htest-dev%2Fhtest-html","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htest-dev%2Fhtest-html/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htest-dev%2Fhtest-html/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htest-dev%2Fhtest-html/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/htest-dev","download_url":"https://codeload.github.com/htest-dev/htest-html/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htest-dev%2Fhtest-html/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30054175,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T17:46:22.538Z","status":"ssl_error","status_checked_at":"2026-03-03T17:46:22.036Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["testing","unit-testing"],"created_at":"2026-03-03T18:14:07.909Z","updated_at":"2026-03-03T18:14:08.797Z","avatar_url":"https://github.com/htest-dev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cnav class=\"sidebar toc\" id=\"main-contents\"\u003e\n\n- [Installation](#installation)\n- [Defining tests](#defining-tests)\n\t- [`data-test` attribute](#data-test-attribute)\n\t- [`data-columns` attribute](#data-columns-attribute)\n\t- [`data-click` attribute](#data-click-attribute)\n\t- [`data-error` attribute](#data-error-attribute)\n\t- [`$out()` and `$outln()` functions](#out-and-outln-functions)\n- [Running tests](#running-tests)\n- [Isolating tests](#isolating-tests)\n\n\u003c/nav\u003e\n\n\u003cmain\u003e\n\n# HTML-first tests\n\nWhile you can run any hTests in the browser,\nyou can also write tests directly in HTML,\nwithout any JS file being involved.\n\nThese tests can *only* run in the browser, but can be useful for testing UI-heavy code.\nThe pass-criteria extends beyond value matching or error catching, and could even be things like what CSS selectors match or what the DOM looks like.\nThey are evaluated reactively, so if the HTML changes or the user interacts with the UI, relevant tests are re-evaluated.\nLast, they also support mocking basic interactions like click or focus, via HTML attributes.\n\n## Installation\n\nJust include hTest on the HTML page:\n\n```html\n\u003clink rel=\"stylesheet\" href=\"https://htest.dev/htest.css\" crossorigin /\u003e\n\u003cscript src=\"https://htest.dev/htest.js\" crossorigin\u003e\u003c/script\u003e\n```\n\n## Defining tests\n\nThe primary test format is reftests, i.e. automatic comparison of two things, typically app output with expected (reference) output. When the two match, the test passes (green), otherwise it fails (red).\n\nYou can create reftests by using a table with `class=\"reftest\"`. Each row is a new test. Typically these tables have two columns: output and expected. However, if your test requires initialization data, you can also have 3 columns, and the first one will be ignored in the matching.\n\nTypically these tables are inside sections with HTML like the following:\n\n```html\n\u003csection\u003e\n\t\u003ch1\u003eHeading\u003c/h1\u003e\n\t\u003ctable class=\"reftest\"\u003e\n\t\t\u003c!-- ...tests as \u003ctr\u003es --\u003e\n\t\u003c/table\u003e\n\u003c/section\u003e\n```\n\nThis structure is not necessary for the reftests to work, but it allows you to isolate specific sections, which is often convenient when debugging.\nYou can also isolate an individual row by \u003ckbd\u003eAlt\u003c/kbd\u003e/\u003ckbd\u003eOption\u003c/kbd\u003e + double clicking.\n\nBelow is a short description of the syntax we support.\n\n### `data-test` attribute\n\nThis applies to either the whole table or individual tests and controls how the matching is done.\nBy default the contents of the cells are compared which corresponds to `data-test=\"contents\"`.\n\nOther useful values are:\n\n- `\"selector\"` which treats the reference cell as a selector (or list of a selectors, if using a `\u003cul\u003e`) that the output HTML must match. You can reverse the matching with `class=\"not\"`.\n- `\"numbers\"` which only compares the numbers returned, ignoring all other output. You can specify an epsilon value by using a `data-epsilon` attribute, either on the row or an ancestor.\n- `\"dom\"` which compares both contents and attributes.\n{# - `\"attribute\"` ??? #}\n\nBesides the built-in comparison functions, you can provide your own, by defining a JavaScript function, either as the content of the `data-test` attribute, or by defining a global function.\nIt accepts the 2-3 cells of your test as arguments and should return a truthy value for pass and a falsy value for fail.\n\n### `data-columns` attribute\n\n2 by default, which means there are two columns: ref and test.\nSet it to 3 or more for custom tests that need the previous columns for data.\n\n### `data-click` attribute\n\nAutomatic clicking on elements. It can be placed on either the whole table or individual tests. Its location specifies the root for the selector, if one is specified. Its syntax is (angle brackets indicate a parameter, square brackets mean that something is optional):\n\n```\n[\u003cselector\u003e] [wait \u003cdelay\u003es] [after \u003cevent name\u003e] [\u003ctimes\u003e times]\n```\n\nThe parameters can be specified in any order.\n\nExamples:\n\n- `data-click=\"\"`: Clicks the element it's specified on immediately on `DOMContentLoaded`.\n- `data-click=\".foo\"`: Clicks `.foo` elements immediately on `DOMContentLoaded`.\n- `data-click=\".foo .bar wait 5s after load\"`: Clicks `.foo .bar` elements 5 seconds after the `load` event fires.\n- `data-click=\".foo 3 times after hashchange\"`: Clicks `.foo` elements 3 times after the `hashchange` event.\n- `data-click=\"wait 1s after load\"`: Clicks the element it's specified on 1 second after the `load` event fires.\n- `data-click=\"wait 1s after load 2 times\"`: Same as above, but clicks twice.\n\n### `data-error` attribute\n\nUse on tests that *should* produce an error to pass.\nUse the `data-error` attribute **on the `\u003ctr\u003e`, not the table cell**.\nPut the expected error type in the \"expected\" table cell.\n\n### `$out()` and `$outln()` functions { #out-and-outln-functions }\n\nSometimes what is tested is pure JS output with no UI.\nWhile the [JS-first mode](https://htest.dev/docs/define/) is typically better for those use cases, it is possible to use HTML-first mode as well.\nIn that case, use `\u003cscript\u003e` tags and the `$out()` or `$outln()` functions.\nTheir only difference is that `$outln()` also prints a line break.\n\n## Running tests\n\nHTML-first tests can currently only run in the browser, by opening the HTML file.\n\n## Isolating tests\n\nIt is often useful to isolate a single group of tests, or even a single test so you can debug a particular failure.\n\nTo isolate a group of tests (`\u003csection\u003e`), simply click the link of the section heading.\n\nTo isolate a specific test (`\u003ctr\u003e`), hold down the \u003ckbd\u003eAlt\u003c/kbd\u003e/\u003ckbd\u003eOption\u003c/kbd\u003e key and double click on the table row.\n\n\u003c/main\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtest-dev%2Fhtest-html","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhtest-dev%2Fhtest-html","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtest-dev%2Fhtest-html/lists"}