{"id":19527997,"url":"https://github.com/wixplosives/test-drive","last_synced_at":"2025-04-26T11:32:37.244Z","repository":{"id":34460038,"uuid":"83210619","full_name":"wixplosives/test-drive","owner":"wixplosives","description":"Opinionated library for writing web component tests","archived":false,"fork":false,"pushed_at":"2024-10-29T08:24:58.000Z","size":3640,"stargazers_count":9,"open_issues_count":0,"forks_count":3,"subscribers_count":223,"default_branch":"master","last_synced_at":"2024-10-29T09:46:53.732Z","etag":null,"topics":["async","chai","components","dom","layout","matchers","tdd","testing","web"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/wixplosives.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}},"created_at":"2017-02-26T13:31:06.000Z","updated_at":"2024-10-29T08:25:02.000Z","dependencies_parsed_at":"2023-12-22T22:19:51.633Z","dependency_job_id":"177d81e7-ea74-43b8-a827-f7d93bf0afb6","html_url":"https://github.com/wixplosives/test-drive","commit_stats":{"total_commits":896,"total_committers":11,"mean_commits":81.45454545454545,"dds":0.5513392857142857,"last_synced_commit":"9aca405ece2f421fe3ffeecaec562cdb79242d18"},"previous_names":[],"tags_count":188,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wixplosives%2Ftest-drive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wixplosives%2Ftest-drive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wixplosives%2Ftest-drive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wixplosives%2Ftest-drive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wixplosives","download_url":"https://codeload.github.com/wixplosives/test-drive/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223779648,"owners_count":17201287,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["async","chai","components","dom","layout","matchers","tdd","testing","web"],"created_at":"2024-11-11T01:17:04.976Z","updated_at":"2024-11-11T01:17:05.588Z","avatar_url":"https://github.com/wixplosives.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Test Drive\n\n[![npm version](https://badge.fury.io/js/test-drive.svg)](https://www.npmjs.com/package/test-drive)\n[![Build Status](https://github.com/wixplosives/test-drive/workflows/tests/badge.svg)](https://github.com/wixplosives/test-drive/actions)\n\n**Test Drive** is an opinionated, yet framework-agnostic collection of tools, matchers and helpers for efficient Test Driven Development of web applications, GUIs and client-side components. Based on existing Open Source projects, as well as original contributions and ideas, it provides not only practical and efficient solutions for writing reliable tests, but also methodological guidelines based on long-term experimentation and hard-won lessons.\n\n## Installation\n\ntest-drive can be installed via the npm registry:\n\n```\nnpm i test-drive --save-dev\n```\n\nIf using TypeScript, several @types packages are required as well:\n\n```\nnpm i @types/chai @types/sinon @types/sinon-chai @types/chai-dom @types/chai-as-promised --save-dev\n```\n\n**test-drive** exports _sinon_ and _chai_ via its main entry point. chai's _expect_ is also directly exported, and is pre-loaded with chai-as-promised, chai-dom, sinon-chai, and chai-style assertions.\n\n## How to write tests\n\n### Locating your DOM parts: `selectDOM()`\n\n`selectDom(container: Element, attrName: string = 'data-automation-id')`\n\nReturns DOM selector function for the `container`, using attribute `attrName`.\nDOM selector is a function accepting one or more string identifiers.\n\nExample:\n\n```tsx\nconst select = selectDOM(document.body, 'my-id');\nconst element = select('panel1', 'button-ok');\n```\n\nThis code will find, inside the document body, element with attribute\n\"myId\" containing word \"panel1\" and inside it element with the same\nattribute containing word \"button-ok\".\n\n`element` will be null, if such path cannot be resolved (\"button-ok\" or\neven \"panel1\" cannot be found).\n\nThe function `select` will throw an exception, if the path is ambiguous\n(e.g., \"panel1\" contains more than one \"button-ok\").\n\n### The `.present()` and `.absent()` matchers\n\nOften, components have parts which are sometimes present, sometimes\nabsent, depending on their configuration or state. As there are many\npossibilities how such \"re-appearance\" can be implemented, this kit\nprovides a matcher that abstracts such internal implementation away.\n\nExample:\n\n```tsx\nexpect(element).to.be.present();\nexpect(element).to.be.absent();\n\nexpect(element).not.to.be.present();\nexpect(element).not.to.be.absent();\n```\n\n\"Presence\" is defined as follows:\n\n- \"element\" is not null\n- \"element\" is an instance of `Element`\n- some part of \"element\" has real size (defined as `ClientRect` whose\n  both `width` and `height` are greater than zero)\n\n(This definition is inspired by [jQuery's `:visible` selector](https://api.jquery.com/visible-selector/), but not\nnecessarily compliant with it.)\n\n### Layout Matchers\n\nUsing layout matchers, component developers can implement tests which assert relations between various parts of the\ncomponent in terms of position in the document. Layout matchers abstract away the actual DOM structure and CSS rules,\nas they are based solely on\n[absolute location of bounding rectangles](https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects). With\nthe right **combination** of layout matchers, one should be able describe most of spatial relationships within components.\n\nThe parts are passed as references to `HTMLElement`.\n\n[Tests of layout matchers](test/layout.spec.ts) should provide exhaustive examples on how to use the matchers.\n\n### Placement\n\n`.insideOf(x)` asserts that the subject is completely within the boundaries of element `x`.\n\n`.outsideOf(x)` asserts the the subject is completely outside the boundaries of element `x`.\n\nIf the subject is partly inside and partly outside, none of the matchers passes.\n\nExample:\n\n```javascript\nexpect(button).to.be.insideOf(panel);\n```\n\n### Box Properties\n\nBox properties of an element (`width`, `height`, `left`, `top`, `right`, `bottom`) can be measured\nand asserted with numeric matchers, such as:\n\n```javascript\nexpect(button1).to.have.width.equal(10);\n```\n\nElements can also be compared with `greaterThan()`, `above()`, `lessThan()`, `below()`, `at.least()` and `at.most()`:\n\n```javascript\nexpect(button1).to.have.height.greaterThan(button2);\n```\n\nAt the same time, numeric comparisons will still work:\n\n```javascript\nexpect(button1).to.have.height.greaterThan(10);\n```\n\nNote that `top` and `bottom` will be compared as numbers. So `bottom = 50` will still be \"below\" `bottom = 100`, even though\nvisually it will, of course, appear \"above\".\n\n### Alignment\n\n`.horizontallyAligned(\"left\" | \"center\" | \"right, tolerance = 0.0)`\n\n`.verticallyAligned(\"top\" | \"center\" | \"bottom\", tolerance = 0.0)`\n\nThe alignment matchers assert that _all elements within a list_ are properly aligned with each other, with optional tolerance range.\n\nExample:\n\n```javascript\nexpect([button1, button2, button3]).to.be.verticallyAligned('top', 1.5);\n```\n\n### Sequence\n\n`.inHorizontalSequence({ distance = 0.0, tolerance = 1.0 })`\n\n`.inVerticalSequence({ distance = 0.0, tolerance = 1.0 })`\n\nAsserts that _all elements within a list_ form uninterrupted sequence, one adjacent to the other, without gaps.\n\nExample:\n\n```javascript\nexpect([button1, button2, button3]).to.be.inHorizontalSequence({ distance: 10.0 });\n```\n\n### Style\n\n_via [chai-style](https://github.com/darlanmendonca/chai-style)_\n\n`.style(styleName, styleValue)`\n\nAsserts that element has style attribute with matching value, regardless of browser-specific value.\n\nExample:\n\n```javascript\nexpect(button).to.have.style('background-color', 'green');\n```\n\n# License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwixplosives%2Ftest-drive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwixplosives%2Ftest-drive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwixplosives%2Ftest-drive/lists"}