{"id":25925304,"url":"https://github.com/umamiappearance/nobrocote","last_synced_at":"2026-05-09T03:39:20.662Z","repository":{"id":39710990,"uuid":"493161503","full_name":"UmamiAppearance/NoBroCote","owner":"UmamiAppearance","description":"Node Browser Code testing. Run unit tests on your JavaScript code for the browser.","archived":false,"fork":false,"pushed_at":"2023-07-16T21:29:41.000Z","size":432,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-07T03:46:24.985Z","etag":null,"topics":["browser","node","puppeteer","testing","unit"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UmamiAppearance.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":"2022-05-17T08:25:51.000Z","updated_at":"2023-07-18T09:12:46.000Z","dependencies_parsed_at":"2025-03-03T18:48:03.568Z","dependency_job_id":"1020f0a3-ad93-477a-bf24-da21d6f06cb8","html_url":"https://github.com/UmamiAppearance/NoBroCote","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/UmamiAppearance/NoBroCote","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UmamiAppearance%2FNoBroCote","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UmamiAppearance%2FNoBroCote/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UmamiAppearance%2FNoBroCote/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UmamiAppearance%2FNoBroCote/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UmamiAppearance","download_url":"https://codeload.github.com/UmamiAppearance/NoBroCote/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UmamiAppearance%2FNoBroCote/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268248600,"owners_count":24219555,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["browser","node","puppeteer","testing","unit"],"created_at":"2025-03-03T18:47:53.990Z","updated_at":"2026-05-09T03:39:20.633Z","avatar_url":"https://github.com/UmamiAppearance.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NoBroCote\n[![License](https://img.shields.io/github/license/UmamiAppearance/NoBroCote?color=009911\u0026style=for-the-badge)](./LICENSE)\n[![npm](https://img.shields.io/npm/v/no-bro-cote?color=009911\u0026style=for-the-badge)](https://www.npmjs.com/package/no-bro-cote)\n\n\n**No**de **Bro**wser **Co**de **te**sting. _Run unit tests on your JavaScript code for the browser._  \n  \n**NoBroCote** is designed for the automation of testing JavaScript code which is made for the browser. It provides methods to run the code units inside of a headless browser via [Puppeteer](https://github.com/puppeteer/puppeteer). Unlike many of the big players in code testing it is not a swiss army knife for every purpose, but particularly to test the code designed for the browser via node, without having to open a browser, and also without writing the test environment from scratch every time.  \n  \n_No big learning curve involved!_ A Unit takes a name, an expected result and a function, which is the test, that's all. \n\n## Use case\nThis software is designed to test if an application for the browser is correctly working.\n - Is it loading into the HTML page?\n - Is it creating the required DOM elements?\n - Is it responding?\n - Is it serving the correct output?\n - etc.\n\n_It is not suitable for UI tests_, reacting to (touch) input and anything like that, or testing if the code is running consistent over different browsers.\n\n## Installation\n**NoBroCote** is made for unit tests with node.js, therefore a installation via npm is advisable. As it is most likely is only needed for testing with the ``--save-dev`` flag.\n\n```sh\nnpm install no-brote-cote --save-dev\n```\n\n## Usage\nThe first step is to create a new ``.js`` file (most likely in your test folder), [import](#importing) a `test`-instance, create one ore more a [test units](#creating-test-units), finally [initialize](#initializing-the-tests).\n    \n**(Psst. No 'time' for reading? Jump straight to a basic [sample code](#basic-sample-code).)**  \n  \nTo run the test(s), you can use the [**CLI**](#cli).\n\n\n### Importing\nInside of your js-file, import a `test`-instance.  \n```js\nimport { test } from \"no-bro-code\";\n```\n\n\n### Creating Test Units\nNow it is time to create a test unit. A unit takes:  \n- ``name`` _\\\u003cstring\\\u003e_ Unit Name\n- ``expect`` _\\\u003c*\\\u003e_ Expected result \n- ``fn`` _\\\u003cFunction\\\u003e_ The actual test. A function for testing.\n- ``fnArgs`` _\\\u003c...any\\\u003e_ Optional parameters for the function. \n\nThe function has access to the html page. It acts like a single function you would execute in a script tag. It has access to all scripts and modules passed via ``addScript`` or ``addImport``. The function can be asynchronous or not. It must return something which can be compared with the expected result.  \n\n**Example:**  \n```js\ntest.makeUnit(\n    \"my first unit\",\n    \"hello\",\n    (greeting) =\u003e {\n        document.body.textContent = greeting;\n        return document.body.textContent;\n    },\n    \"hello\"\n);\n```\n\n### Controlling the Test Assertion\nThe regular assertion compares the expected value and the result for equality without type conversion (===). If this is not the desired behavior, there are some operators available to control the assertion process. Operators are activated by passing them to the expect parameter of a ``makeUnit`` method.  \n  \n_Available operators are:_\n -  ``!|`` not\n - ``!=|`` not, with type conversion\n -  ``||`` or, values can be separated with a '|', like this: ||valueA|valueB|valueC\n - ``==|`` equality, with type conversion\n\n**Examples:**\n```js\ntest.makeUnit(\n    \"notTest\",\n    \"!|cat\",\n    () =\u003e {\n        document.body.textContent = \"dog\";\n        return document.body.textContent;\n    }\n);\n\ntest.makeUnit(\n    \"orTest\",\n    \"||cat|dog|bird\",\n    () =\u003e {\n        const pickPet = () =\u003e [\"cat\", \"dog\", \"bird\"].at(Math.floor(Math.random()*3));\n        document.body.textContent = pickPet();\n        return document.body.textContent;\n    }\n);\n```\n\n\n### Controlling Errors\nSometimes it is necessary to test if an error is thrown. Similar to the just featured operators there are operators for errors (those keywords are also passed to the expect parameter).\n_Those are:\n - ``e|`` (for allowing all errors)\n - ``e|EvalError``\n - ``e|InternalError``\n - ``e|RangeError``\n - ``e|ReferenceError``\n - ``e|SyntaxError``\n - ``e|TypeError``\n - ``e|URIError``\n\n**Example:**\n\n```js\ntest.makeUnit(\n    \"expectErrorTest\",\n    \"e|TypeError\",\n    () =\u003e {\n        throw new TypeError(\"I am glad this error was raised!\");\n    }\n);\n```\n\n#### Custom Errors\nCustom errors can be also be added to error list:\n```js\n// first create the error (or import it from somewhere else)\nclass ValidationError extends Error {\n    constructor(message) {\n        super(message);\n        this.name = \"ValidationError\";\n    }\n}\n\n// second append it to the error list\ntest.errorList.push(ValidationError.name);\n\n// now it can be used with: 'e|ValidationError'\n```\n\n### Expecting a Failure\nAssuming a situation, where an error should be raised, but the test should not fail. It is possible to anyhow count this as a success. With the setting:\n```js\ntest.expectFailure = true;\n```\n\\- at least one unit has to fail.\n\n\n### Importing Scripts and Modules\n\n#### addScript\nThis method appends a script tag to the html page. The method requires an object which can have the following keys (as defined by **Puppeteer**):\n - ``url`` _\\\u003cstring\\\u003e_ URL of a script to be added.\n - ``path`` _\\\u003cstring\\\u003e_ Path to the JavaScript file to be injected into frame. If path is a relative path, then it is resolved relative to projects root directory (cwd).\n - ``content`` _\\\u003cstring\\\u003e_ Raw JavaScript content to be injected into frame.\n - ``type`` _\\\u003cstring\\\u003e_ Script type. Use 'module' in order to load a Javascript ES6 module.\n \n_You can also pass an array of objects. An **example** may look like so:_\n\n```js\ntest.addScript({\n    path: \"./path/to/script\"\n});\n ```\n\nAlso see: [devdocs.io/puppeteer](https://devdocs.io/puppeteer/).\n\n#### addImport\nThis method provides ES6 imports for the test runner. In contrast to ``addScripts``, this method needs a valid ES6 import statement as a string. These imports are directly accessible by the test units as they are part of one script tag in the browser.\n - Relative imports are resolved relative to the projects root directory (cwd).\n - Multiple imports can be passed as an array. _A possible **example** may be as follows:_\n\n```js\ntest.addImport('import myModule from \"./path/to/module\"');\n ```\n\n### HTML Page\nBy default a very skeleton of an HTML page is getting opened, on which the tests are getting injected. But also it is possible to load a custom HTML page. The page has to be reachable from the projects root folder and its path has to be declared relative to root. Assuming a HTML page with the path `./test/fixtures/page.html` the declaration inside of the test file may look as follows:\n\n```js\ntest.htmlPage = \"./test/fixtures/page.html\";\n```\n\n### Server Port\nBy default the server runs on port ``10000``. If the port is already in use the port number is raised by one until an open port was found. The initial port can be changed, if this is a bad starting point for any reason. Simply declare another port in that case.\n```js\ntest.port = 8080;\n```\n\n\n### Initializing the tests\nAfter all imports are done and all units are declared, all that is left to do is to set the following line at the end of the file:\n\n```js\ntest.init();\n ```\n\nThe js file could now be called with node from the projects root directory:\n\n```sh\nnode ./path/to/file.js\n```\n\nMuch more convenient is to use the [CLI](#cli), by adding it to the test section of your ``package.json``\n\n```json\n\"scripts\": {\n    \"test\": \"no-bo-cote\",\n}\n```\n\n\n## Basic Sample Code\n```js\nimport { test } from \"no-bro-cote\";\n\n// imports (optional)\ntest.addScript({\n    path: \"./path/to/script\"\n});\n\ntest.addImport('import myModule from \"./path/to/module\"');\n\n\n// units\ntest.makeUnit(\n    \"myFirstUnit\",\n    \"hello\",\n    () =\u003e {\n        document.body.textContent = \"hello\";\n        return document.body.textContent;\n    }\n);\n\ntest.makeUnit(\n    \"myNotUnit\",\n    \"!|hello\",\n    async (argExample) =\u003e {\n        document.body.textContent = argExample;\n        return document.body.textContent;\n    },\n    \"world\"\n);\n\ntest.makeUnit(\n    \"myExpectErrorUnit\",\n    \"e|ReferenceError\",\n    () =\u003e {\n        const thisIsPython = False;\n    }\n);\n\n\n// last step -\u003e the file is now callable from the projects root directory and by the CLI\ntest.init();\n```\n\n## CLI\nThe **CLI** is for the most part inspired/adopted from the great [AVA](https://github.com/avajs/ava/blob/main/docs/05-command-line.md) test runner.\n\n```console\nno-bro-cote [\u003cpattern\u003e...]\n\nPositionals:\n  pattern  Select which test files to run. Leave empty if you want to run all\n           test files as per your configuration. Accepts glob and minimatch\n           patterns, directories that (recursively) contain test files, and\n           relative or absolute file paths.                             [string]\n\nOptions:\n      --help              Show help                                    [boolean]\n      --version           Show version number                          [boolean]\n      --debug             Enable debug mode                            [boolean]\n      --fail-fast         Stop after first test failure                [boolean]\n      --ignore-coherence  Skip test for a coherent test file           [boolean]\n  -s, --serial            Run tests serially                           [boolean]\n\nExamples:\n  no-bro-cote\n  no-bro-cote test.js\n  no-bro-cote ./test/\n  no-bro-cote \"**/**test.js\"\n  ```\n\nIf no patterns are provided **no-bro-cote** searches for test files using the following patterns:\n\n* `test.js`\n* `src/test.js`\n* `source/test.js`\n* `**/test-*.js`\n* `**/*.spec.js`\n* `**/*.test.js`\n* `**/test/**/*.js`\n* `**/tests/**/*.js`\n* `**/__tests__/**/*.js`\n\nFiles inside `node_modules` and files inside directories starting with `.git` are *always* ignored. So are files starting with `_` or inside of directories that start with a single `_`. Additionally, files matching these patterns are ignored by default, unless different patterns are configured:\n\n* `**/__tests__/**/__helper__/**/*`\n* `**/__tests__/**/__helpers__/**/*`\n* `**/__tests__/**/__fixture__/**/*`\n* `**/__tests__/**/__fixtures__/**/*`\n* `**/test/**/helper/**/*`\n* `**/test/**/helpers/**/*`\n* `**/test/**/fixture/**/*`\n* `**/test/**/fixtures/**/*`\n* `**/tests/**/helper/**/*`\n* `**/tests/**/helpers/**/*`\n* `**/tests/**/fixture/**/*`\n* `**/tests/**/fixtures/**/*`\n\nWhen using `npm test`, you can pass positional arguments directly `npm test test2.js`, but flags needs to be passed like `npm test -- --debug`.\n\n\n### Configuration\nAll of the **CLI** [options](#options) can be configured in the `no-bro-cote` section of your `package.json` file. This allows you to modify the default behavior of the `no-bro-cote` command, so you don't have to repeatedly type the same options on the command prompt.\n\nTo ignore files, prefix the pattern with an `!` (exclamation mark).\n\n**`package.json`:**\n\n```json\n{\n  \"no-bro-cote\": {\n    \"debug\": false,\n    \"extensions\": [\n      \"js\",\n      \"mjs\"\n    ],\n    \"failFast\": true,\n    \"files\": [\n      \"test/**/*\",\n      \"!test/exclude-files-in-this-directory\",\n      \"!**/exclude-files-with-this-name.*\"\n    ],\n    \"ignoreCoherence\": false, \n    \"serial\": true\n  }\n}\n```\n\nArguments passed to the CLI will always take precedence over the CLI options configured in `package.json`.\n\n#### Options\n\n- `debug`: enables debug mode if set to true. Let's no-bro-cote run the tests serially and provides verbose console output\n- `extensions`: extensions of test files. Setting this option overrides the default `[\"mjs\", \"js\"]` value\n- `failFast`: stop running further tests once a test fails\n- `files`: an array of glob patterns to select test files. Files with an underscore prefix are ignored. By default only selects files with `mjs` \u0026 `js` extensions, even if the pattern matches other files. Specify `extensions` to allow other file extensions\n- `ignoreCoherence`: Every test file is getting executed as a subprocess. To prevent the CLI to run every js-file, that is found, the source code is getting analyzed if it is a no-bro-cote test file. Setting this option to true, disables this check (which might be dangerous).\n- `serial`: By default the tests are running concurrently. Setting this option to true, only one test file runs at a time. \n\n\n_Note that all arguments provided on the CLI overrides the options configured in `package.json`._\n\n\n## License\nThis work is licensed under [GPL-3.0](https://opensource.org/licenses/GPL-3.0).\n\n\n\n```\n                                         ....\n                                       ..;ddc...\n                                     ..:do,,cdl'..\n                                   ..:do,'...':do'..\n                                ...cdo,'.......':do;..\n                              ..'ldl,............';od:..\n                            ..'ldc,................',odc...\n                          ..'ld:'.....................,ldl'..\n                        ..'oxc'..pq....po.....,ooOoo,...':do'..\n                      ..,od:,....XWXc..kN'...c0k'''x0l....':do,..\n                    ..,dd;'......X0cXx.kN'..,Wx.....xW;.....';dd;..\n                  ..;dd;'........X0..O0ON'..'X0'...'0X,.......',odc..\n                ..;dd;'..........X0...o0N'...\"okdggko\"...........,ldc...\n              ..:do,'..............................................,ldl'..\n            ..:xo,'..................................................':xo,..\n          ..cdo,'.k00000000Oxo,.....c00000000Oko;........:dOKXNNXKOd:..';dd;..\n       ...cdl,....KMMMNOOOXMMMW:....cMMMM000XMMMMl.....;KMMMW0kkONMMMK;..',dd;..\n     ..'ldc'......KMMM....'MMMMd....cMMMM....0MMM0....;WMMMO'....'kMMMW;...',odc...\n   ..'lxc'........KMMMNOOOXMMWO'....cMMMM...oNMMWc....OMMMM'.......NMMMO......'cdl'..\n ..'odc,..........KMMMW00KXMMW0c....cMMMMMMMMMM0,.....0MMMW........XMMMK........'cdo'..\n...lxc'...........KMMP.....oMMMM,...cMMMM::lOMMMX:....oMMMMl......;MMMMl........,ldc...\n  ..'lxl,.........KMMM....,KMMMW'...cMMMM'...dMMMWc....xMMMMk....xWMMMd.......,lx:..\n    ..'cdo,.......KMMMMMMMMMWXk;....cMMMM'....oMMMMo....ikXMMMMMMMMXkj.....',odc..\n       ..;dd;'....kooooooooou*'.....cgggg......:uoOX.......*MMMMMM*......,dd;..\n         ..;od;'.......................................................',dd;..\n           ..,dx:'...................................................';dd;..\n             ..'ldc'........;dkXX:..;dkxkl..MXXXXXM..MXXXM.........':do,..\n               ...cxl,.....:MX,....,WK'.oMx...cMd....MXL,,.......';xo'..\n                  ..cdd,'..:MK,....;WK'.lMx...cMd....MXP\"\".....':do'..\n                    ..;dd,'.;xOXX:..;xOkOl....cOd....MXXXM...,cxo'..\n                      ..,od;'..............................'cdl'..\n                        ..'oxc,..........................'cxc...\n                          ..'ldl'......................,odl...\n                            ...cxl,..................,od:...\n                               ..:do;'.............,od:..\n                                 ..,od:'........';dd;..\n                                   ..'ox:'....';dd,..\n                                     ..'ldc'';do,..\n                                       ...ldxo'..\n                                         ...o..\n                                            .\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumamiappearance%2Fnobrocote","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fumamiappearance%2Fnobrocote","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumamiappearance%2Fnobrocote/lists"}