{"id":22129301,"url":"https://github.com/gparlakov/scuri","last_synced_at":"2025-05-07T13:07:40.759Z","repository":{"id":34932073,"uuid":"187455102","full_name":"gparlakov/scuri","owner":"gparlakov","description":"Automate Angular unit test and boilerplate with this schematic.","archived":false,"fork":false,"pushed_at":"2024-06-21T13:09:33.000Z","size":9916,"stargazers_count":67,"open_issues_count":30,"forks_count":7,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-07T13:07:34.311Z","etag":null,"topics":["angular","boilerplate","enterprise","schematics","spec-schematic","typescript","unittest","unittests-generation"],"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/gparlakov.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":"npm/scuri","community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-05-19T09:04:01.000Z","updated_at":"2024-08-28T20:34:28.000Z","dependencies_parsed_at":"2024-04-23T08:35:36.083Z","dependency_job_id":null,"html_url":"https://github.com/gparlakov/scuri","commit_stats":{"total_commits":342,"total_committers":6,"mean_commits":57.0,"dds":0.07894736842105265,"last_synced_commit":"43052f74d2841db3cd19cb1e810e0cad6047ef12"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gparlakov%2Fscuri","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gparlakov%2Fscuri/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gparlakov%2Fscuri/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gparlakov%2Fscuri/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gparlakov","download_url":"https://codeload.github.com/gparlakov/scuri/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252883219,"owners_count":21819161,"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":["angular","boilerplate","enterprise","schematics","spec-schematic","typescript","unittest","unittests-generation"],"created_at":"2024-12-01T17:59:29.256Z","updated_at":"2025-05-07T13:07:40.734Z","avatar_url":"https://github.com/gparlakov.png","language":"TypeScript","funding_links":["https://tidelift.com/funding/github/npm/scuri","https://tidelift.com/subscription/pkg/npm-scuri?utm_source=npm-scuri\u0026utm_medium=referral\u0026utm_campaign=enterprise\u0026utm_term=repo","https://www.buymeacoffee.com/bHQk8Cu"],"categories":["TypeScript"],"sub_categories":[],"readme":"# SCuri[\\*](#scuri-name)\n\n[![Build Status](https://dev.azure.com/gparlakov/Scuri/_apis/build/status/Scuri%20PR%20Check?branchName=master)](https://dev.azure.com/gparlakov/Scuri/_build/latest?definitionId=4\u0026branchName=master)\n\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n[![All Contributors](https://img.shields.io/badge/all_contributors-6-orange.svg?style=flat-square)](#contributors-)\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\n### **Automates unit test boilerplate** for **Angular** components/services/directives/etc. It will **generate** spec for you and help you **update** it when dependencies are added or removed!\n\n\u003cbr /\u003e\n\n\u003e _Powered by [Schematics](https://angular.io/guide/schematics) and [TypeScript compiler](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API)_\n\n## Links\n\n[![](./docs/VSCode_20px.png)](https://marketplace.visualstudio.com/items?itemName=gparlakov.scuri-code) [VS Code extension](https://marketplace.visualstudio.com/items?itemName=gparlakov.scuri-code) available!\n\n🐱‍👤[Need a custom template?](./docs/custom-template-guide.md)\n\n🤙Have some feedback or need a feature? [SCuri discussion on github](https://github.com/gparlakov/scuri/discussions/110)\n\n🤵[Need commercial-quality coverage for SCuri?](#scuri-for-enterprise)\n\n💵[Support us](#like-it)\n\n## Why?\n\n**After** a component has been **created** it is **boring and tedious** to do the tests - and we often **don't**. SCuri[\\*](#scuri-name) tries to jump-start that by walking the component's constructor, parsing the dependencies and creating mocks for each of them, and then including them in the spec.\n\n## Features\n\n### Create a test case from scratch\n\n![missing create spec video](./docs/new-v2.gif)\n\nThe video shows how to use `schematics scuri:spec --name src\\app\\my-com\\my-com.component.ts` to create a spec from scratch (if already created see **update** or use **--force** to overwrite).\n\n\u003e For Angular CLI \u003e= 6 `ng g scuri:spec --name src\\app\\my-com\\my-com.component.ts` could be used instead.\n\n\u003e **--name** is now optional `ng g scuri:spec my-com.component.ts` or `npx schematics scuri:spec my-com.component.ts`\n\nSee details [down here](#create-spec-from-scratch).\n\n### Update existing test\n\n![missing update spec video](./docs/update.gif)\n\nShows how we begin with an outdated test:\n\n-   missing `it` test case for one of the public methods (`getData`)\n-   missing dependency `HttpClient` to instantiate the component\n\nAnd after `schematics scuri:spec --name src\\app\\my-com\\my-com.component.ts --update` command we get the updated test - dependency and a scaffold test case added.\n\n\u003e For Angular CLI \u003e= 6 `ng g scuri:spec --name src\\app\\my-com\\my-com.component.ts --update` could be used instead.\n\nSee details [down here](#update-existing-spec)\n\n### AutoSpy\n\n![missing autospy video](./docs/autospy.gif)\nGenerates an `autoSpy` function that takes a type and returns an object with the same type plus all its methods are mocked i.e. `jasmine.spy()` or `jest.fn()`.\n\nSee details [down here](#autospy-1).\nNeeds tsconfig path setup -\u003e [there](#autospy-and-typescript).\n\n## Getting started / Setup\n\nUsing VS Code? Just install the [**SCuri** VS Code extension](https://marketplace.visualstudio.com/items?itemName=gparlakov.scuri-code)\n\n### Command line setup\n\n1. Install deps\n\n    ```bash\n    npm install -D scuri\n    ng g scuri:spec --name src/app/app.component.ts\n    ```\n\n2. Generate autospy\n\n    ```bash\n    ng g scuri:autospy\n    ```\n\n    [Details and older Angular versions](#autospy-1)\n\n3. Tell **Typescript** where to find `autoSpy` by adding `autoSpy` to `paths`:\n\n    ```json\n    {\n        ...\n        \"compilerOptions\": {\n            ...\n            \"baseUrl\": \".\",\n            \"paths\": {\n                \"autoSpy\": [\"./src/auto-spy\"]\n            }\n        }\n    }\n    ```\n\n    Details [here](#Autospy-and-Typescript)\n\n4. Start using scuri:\n\n    ```sh\n    ng g scuri:spec --name src/app/app.component.ts\n    ```\n\nIf you get `Error: Invalid rule result: Function().` see the [troubleshooting section below](#rule-result-function).\n\n## Details\n\n### Create spec from scratch\n\n```sh\nng g scuri:spec --name src/app/app.component.ts\n```\n\nor\n\n```sh\nnpx schematics scuri:spec --name src/app/app.component.ts\n```\n\nRequires `--name` - an existing `.ts` file with one `class` (Component/Service/Directive/etc.) and NONE existing `.spec.ts` file.\n\n### Overwrite existing spec\n\n```sh\nng g scuri:spec --name src/app/app.component.ts --force\n```\n\nor\n\n```sh\nnpx schematics scuri:spec --name src/app/app.component.ts --force\n```\n\nRequires `--name` - an existing `.ts` file with one `class` (Component/Service/Directive/etc.). Will overwrite any existing `.spec.ts` file.\n\n\u003e This might be useful in certain more complex cases. Using a diff tool one could easily combine the preexisting and newly created (overwritten) content - just like a merge conflict is resolved.\n\n### Update existing spec\n\n```sh\nng g scuri:spec --name src/app/app.component.ts --update\n```\n\nor\n\n```sh\nnpx schematics scuri:spec --name src/app/app.component.ts --update\n```\n\nRequires `--name` - an existing `.ts` file with one `class` (Component/Service/Directive/etc.) and one existing `.spec.ts` file where the update will happen.\n\n### AutoSpy\n\nTo generate an `auto-spy.ts` file with the type and function which can be used for automating mock creation, use:\n\n`ng g scuri:autospy`\n\nSee the [Autospy](https://github.com/gparlakov/scuri/wiki/Autospy) wiki page.\n\n#### Using older versions of Angular?\n\n-   Angular v5, v4, v2:\n    `bash npm i -g @angular-devkit/schematics-cli npm i -D scuri schematics scuri:autospy --legacy`\n    _Notice the --legacy flag. It's required due to typescript being less than 2.8. See flags below_\n\n#### Using Jest\n\n`ng g scuri:autospy --for jest`\n\nOr\n\n`schematics scuri:autospy --for jest`\n\nVersions and flags\n\n| angular        | jest / jasmine | command                                        |\n| -------------- | -------------- | ---------------------------------------------- |\n| 2,4,5          | jasmine        | `schematics scuri:autospy --legacy`            |\n|                | jest           | `schematics scuri:autospy --for jest --legacy` |\n| 6, 7, 8 and up | jasmine        | `ng g scuri:autospy`                           |\n|                | jest           | `ng g scuri:autospy --for jest`                |\n\nAll Angular versions after and including 6 can use the Angular CLI - `ng generate scuri:autospy`.\n\nFlags:\n\n-   `--for` with accepted values `jest` and `jasmine` (default is `jasmine`)\n-   `--legacy` for generating a type compatible with typescript \u003c 2.8 (namely the conditional types feature)\n\nExamples:\n`ng g scuri:autospy --for jest --legacy` would generate a ts\u003c2.8, jest-compatible `autoSpy` type and function\n`ng g scuri:autospy` would generate a ts\u003e2.8, jasmine-compatible `autoSpy` type and function\n\n### Autospy and Typescript\n\nAfter creating the `auto-spy.ts` file as a result of the `scuri:autospy` schematic invocation we need to make sure its properly imported in our tests. To that end and keeping in mind that `autoSpy` is being imported in the created tests as `import { autoSpy } from 'autoSpy';`. To make that an actual import one could add this line to `tsconfig.json`:\n\n```json\n{\n    \"compilerOptions\": {\n        \"baseUrl\": \".\", // This must be specified if \"paths\" is.\n        \"paths\": {\n            \"autospy\": [\"./src/auto-spy\"] // This mapping is relative to \"baseUrl\"\n        }\n    }\n}\n```\n\nThis is assuming `auto-spy.ts` was created inside `./src` folder. Edit as appropriate for your specific case.\n\nSee [here](https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping) for **path** details\n\n## 🛣 Road map \u003ca id=\"road-map\" href=\"#road-map\"\u003e~\u003c/a\u003e\n\n-   [x] Create spec from scratch (or overwrite existing with `--force`)\n-   [x] Update existing spec - add/remove dependencies\n-   [x] Create one scaffold `it` test case for each public method\n-   [x] On Update add `it`-s for newly added public methods\n-   [x] Generate autoSpy by `scuri:autospy` (support jest, jasmine and ts with and w/o conditional types)\n-   [x] Support traditional Angular cli generated tests (with `--update`)\n    -   [x] Add `setup` function when missing\n    -   [x] Update dependencies\n-   [x] Allow configuration via file (.scuri.json)\n-   [ ] ([workaround](#autospy-and-typescript)) Import `autoSpy` function automatically - now imported as `import { autoSpy } from 'autoSpy';`\n\n## S.C.u.r.i. \u003ca id=\"scuri-name\" href=\"#scuri-name\"\u003e\\*\u003c/a\u003e\n\nWhat's with the name?\n\nA spec generator schematic - **S**pec **C**reate **U**pdate **R**ead (class - component, service, directive and dependencies) **I**ncorporate (them in the spec generated/updated)\n\n## Configuring\n\nScuri can use configuration from the following list by default (package.json .scurirc .scurirc.json .scurirc.yml .scurirc.yaml scurirc.js scurirc.config.js).\n\n### Example package.json\n\n```json\n{\n  \"name\": \"my-app\",\n  ...\n  \"scuri\": {\n      \"classTemplate\": \"src/templates/__specFileName__.template\",\n      \"functionTemplate\": \"src/templates/__specFileName__.template\"\n  }\n}\n```\n\n### Example .scurirc\n\n```json\n{\n    \"classTemplate\": \"src/templates/__specFileName__.template\",\n    \"functionTemplate\": \"src/templates/__specFileName__.template\"\n}\n```\n\n## Custom templates\n\nHead over to the [custom template guide](./docs/custom-template-guide.md) or see the short explanation below:\n\n-   **classTemplate** - a location of a custom class template to be used. Here's a [gist](https://gist.github.com/gparlakov/f299011829e229c9d37cf0cb38506d97) of starter template that explains what properties are available to the class template\n    -   starter [https://gist.github.com/gparlakov/f299011829e229c9d37cf0cb38506d97](https://gist.github.com/gparlakov/f299011829e229c9d37cf0cb38506d97)\n    -   issue with a specific example [link](https://github.com/gparlakov/scuri/issues/32#issuecomment-946332209)\n-   **functionTemplate** - a location of a custom function template to be used. Here's a [gist](https://gist.github.com/gparlakov/0b9b94f8140687bb3b1db1772503bd0d) of a starter template that shows what properties are available to the function template\n\n## Troubleshooting\n\n### Migrating from 1.1 to 1.2 broke the custom template!\n\nTry using `__specFileName__.template` for your template name. The `__specFileName__` gets interpreted while creating the spec. There are other variables available too - see the [custom template guide](./docs/custom-template-guide.md)\n\n### Rule result Function\n\nTo workaround the `Error: Invalid rule result: Function().` install schematics separately and call `scuri` with that.\n\n```sh\nnpm install -D scuri\nnpm i -g @angular-devkit/schematics-cli\nschematics scuri:spec --name src/app/app.component.ts\n```\n\nor if you don't want to install the `schematics` cli globally and have `npm version 6 and above` you can\n\n```sh\nnpm install -D scuri @angular-devkit/schematics-cli\nnpx schematics scuri:spec --name src/app/app.component.ts\n```\n\n## Contributing\n\n[Link](./CONTRIBUTING.md)\n\n## SCuri for enterprise\n\nAvailable as part of the Tidelift Subscription\n\nThe maintainers of SCuri and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open-source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-scuri?utm_source=npm-scuri\u0026utm_medium=referral\u0026utm_campaign=enterprise\u0026utm_term=repo)\n\n## Contributors ✨\n\nThanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/gparlakov\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/3482199?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eGeorgi Parlakov\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/gparlakov/scuri/commits?author=gparlakov\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"#ideas-gparlakov\" title=\"Ideas, Planning, \u0026 Feedback\"\u003e🤔\u003c/a\u003e \u003ca href=\"https://github.com/gparlakov/scuri/commits?author=gparlakov\" title=\"Documentation\"\u003e📖\u003c/a\u003e \u003ca href=\"https://github.com/gparlakov/scuri/commits?author=gparlakov\" title=\"Tests\"\u003e⚠️\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/tziyang-lum\"\u003e\u003cimg src=\"https://avatars3.githubusercontent.com/u/56020413?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTzi Yang\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/gparlakov/scuri/issues?q=author%3Atziyang-lum\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/fgisslen\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/35102084?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003efgisslen\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/gparlakov/scuri/issues?q=author%3Afgisslen\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/danjor\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/3473673?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003edanjor\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/gparlakov/scuri/issues?q=author%3Adanjor\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/features/security\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/27347476?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eDependabot\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"#maintenance-dependabot\" title=\"Maintenance\"\u003e🚧\u003c/a\u003e\u003c/td\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/OSHistory\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/9952252?v=4?s=80\" width=\"80px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eOSHistory\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/gparlakov/scuri/issues?q=author%3AOSHistory\" title=\"Bug reports\"\u003e🐛\u003c/a\u003e \u003ca href=\"https://github.com/gparlakov/scuri/commits?author=OSHistory\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThis project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!\n\n## Like it?\n\nYou like the project and it gives you value? You are considering supporting it? That would be really appreciated!\n\n\u003ca class=\"bmc-button\" target=\"_blank\" href=\"https://www.buymeacoffee.com/bHQk8Cu\"\u003e☕\u003cspan style=\"margin-left:5px;\"\u003eBuy us a coffee\u003c/span\u003e\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgparlakov%2Fscuri","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgparlakov%2Fscuri","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgparlakov%2Fscuri/lists"}