{"id":48008488,"url":"https://github.com/salesforcecli/cli-plugins-testkit","last_synced_at":"2026-04-25T11:00:42.427Z","repository":{"id":37846859,"uuid":"332839775","full_name":"salesforcecli/cli-plugins-testkit","owner":"salesforcecli","description":"Test utilities to assist plugin authors with writing integration, smoke, e2e style testing","archived":false,"fork":false,"pushed_at":"2026-04-18T09:02:01.000Z","size":2678,"stargazers_count":12,"open_issues_count":1,"forks_count":4,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-04-18T11:18:22.587Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/salesforcecli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-01-25T18:13:49.000Z","updated_at":"2026-04-18T09:02:05.000Z","dependencies_parsed_at":"2023-12-09T09:30:36.548Z","dependency_job_id":"3a5cff39-0f7c-4c0c-b55b-228d3fc18a95","html_url":"https://github.com/salesforcecli/cli-plugins-testkit","commit_stats":{"total_commits":595,"total_committers":20,"mean_commits":29.75,"dds":0.6067226890756303,"last_synced_commit":"d83eed64f53cfad5062e20c742fbf2eda99cb0f9"},"previous_names":[],"tags_count":321,"template":false,"template_full_name":null,"purl":"pkg:github/salesforcecli/cli-plugins-testkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforcecli%2Fcli-plugins-testkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforcecli%2Fcli-plugins-testkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforcecli%2Fcli-plugins-testkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforcecli%2Fcli-plugins-testkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/salesforcecli","download_url":"https://codeload.github.com/salesforcecli/cli-plugins-testkit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/salesforcecli%2Fcli-plugins-testkit/sbom","scorecard":{"id":796389,"data":{"date":"2025-08-11","repo":{"name":"github.com/salesforcecli/cli-plugins-testkit","commit":"5762d54d76c5d0e56041c0f9b9d297c107a56870"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4,"checks":[{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Security-Policy","score":9,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Warn: One or no descriptive hints of disclosure, vulnerability, and/or timelines in security policy","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Code-Review","score":0,"reason":"Found 0/8 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/automerge.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/automerge.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/create-github-release.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/create-github-release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/devScripts.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/devScripts.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/failureNotifications.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/failureNotifications.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/notify-slack-on-pr-open.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/notify-slack-on-pr-open.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/onRelease.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/onRelease.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/onRelease.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/onRelease.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/onRelease.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/onRelease.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/validate-pr.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/salesforcecli/cli-plugins-testkit/validate-pr.yml/main?enable=pin","Info:   0 out of   1 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  13 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/automerge.yml:1","Warn: no topLevel permission defined: .github/workflows/create-github-release.yml:1","Warn: no topLevel permission defined: .github/workflows/devScripts.yml:1","Warn: no topLevel permission defined: .github/workflows/failureNotifications.yml:1","Warn: no topLevel permission defined: .github/workflows/notify-slack-on-pr-open.yml:1","Warn: no topLevel permission defined: .github/workflows/onRelease.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Warn: no topLevel permission defined: .github/workflows/validate-pr.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 24 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-23T09:08:11.173Z","repository_id":37846859,"created_at":"2025-08-23T09:08:11.173Z","updated_at":"2025-08-23T09:08:11.173Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32259472,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T09:15:33.318Z","status":"ssl_error","status_checked_at":"2026-04-25T09:15:31.997Z","response_time":59,"last_error":"SSL_read: 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":[],"created_at":"2026-04-04T13:26:54.381Z","updated_at":"2026-04-25T11:00:42.420Z","avatar_url":"https://github.com/salesforcecli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![NPM](https://img.shields.io/npm/v/@salesforce/cli-plugins-testkit.svg)](https://www.npmjs.com/package/@salesforce/cli-plugins-testkit)\n\n# Description\n\nThe @salesforce/cli-plugins-testkit library provides test utilities to assist Salesforce CLI plug-in authors with writing NUTs (non-unit-tests), like integration, smoke, and e2e style testing. For example, you could write tests to ensure your plugin commands execute properly using an isolated Salesforce project, scratch org, and different Salesforce CLI executables.\n\n# Usage\n\nAdd this library as a dev dependencies to your project.\n\n```bash\nyarn add @salesforce/cli-plugins-testkit --dev\n```\n\nCreate a test file and import the utilities from this library that you'd like to use.\n\nUsing a different file extension will help separate your unit tests from your NUTs even if they are in the same directories. For example, if you use `mytest.nut.ts` instead of `mytest.test.ts`, you can have the following scripts in your package.json (assuming mocha).\n\n```json\n{\n  \"scripts\": {\n    \"test\": \"mocha **/*.test.ts\",\n    \"test-nut\": \"mocha **/*.nut.ts\"\n  }\n}\n```\n\n**See [Samples](./SAMPLES.md) doc for many testkit usecases and sample code**\n\n# Example NUTs\n\nHere are some public github repos for plugins that use this library for NUTs:\n\n- [@salesforce/plugin-alias](https://github.com/salesforcecli/plugin-alias/blob/main/test/commands/alias/set.nut.ts)\n- [@salesforce/plugin-auth](https://github.com/salesforcecli/plugin-auth/blob/main/test/commands/org/list/auth.nut.ts)\n- [@salesforce/plugin-config](https://github.com/salesforcecli/plugin-config/blob/main/test/commands/config/list.nut.ts)\n- [@salesforce/plugin-data](https://github.com/salesforcecli/plugin-data/blob/main/test/commands/data/tree/dataTree.nut.ts)\n- [@salesforce/plugin-org](https://github.com/salesforcecli/plugin-org/blob/main/test/nut/listAndDisplay.nut.ts)\n- [@salesforce/plugin-user](https://github.com/salesforcecli/plugin-user/blob/main/test/allCommands.nut.ts)\n\n## Running Commands\n\nAlthough oclif provides a way to run commands locally using the local `bin/run` file...\n\n```typescript\nimport { exec } from 'shelljs';\nconst result = exec('./bin/run mycommand --myflag --json');\nconsole.log(JSON.parse(result.stdout));\n```\n\n...that doesn't provide flexibility to target different CLI executables in Continuous Integration (CI). For example, you may want to run NUTs against the newly published version of your plugin using the latest-rc of the Salesforce CLI to make sure everything still works as expected.\n\nThe testkit provides `execCmd` which uses the `TESTKIT_EXECUTABLE_PATH` environment variable to run a plugin command, in addition to other useful builtin utilties such as json parsing, return type casting (for TypeScript) and command execution timing.\n\n```typescript\nimport { execCmd } from '@salesforce/cli-plugins-testkit';\n\nconst result = execCmd\u003cMyReturntype\u003e('mycommand --myflag --json').jsonOutput;\nexpect(result.name).to.equal('expectedName');\n```\n\n```bash\n# Install the release candidate in the current directory using NPM\nnpm install @salesforce/cli@latest-rc\n\n# Install the newly published version of my plugin\n./node_modules/.bin/sf plugins:install myplugin\n\n# Target the local sf\nexport TESTKIT_EXECUTABLE_PATH=./node_modules/.bin/sf\n\n# Run NUTs (requires a test:nuts script target in the package.json)\nyarn test:nuts\n```\n\nYou will notice that the executable is not configurable in the `execCmd` method directly. If you need to run other commands not located in your plugin, use shelljs directly.\n\n```typescript\nimport { exec } from 'shelljs';\nimport { execCmd } from '@salesforce/cli-plugins-testkit';\n\nawait exec('sf auth:jwt:grant ... --json');\nconst result = await execCmd('mycommand --myflag --json');\n```\n\n# Environment Variables\n\n| Env Var                       | Description                                                                                                     |\n| ----------------------------- | --------------------------------------------------------------------------------------------------------------- |\n| TESTKIT_SESSION_DIR           | Overrides the default directory for the test session.                                                           |\n| TESTKIT_HOMEDIR               | Path to a home directory that the tests will use as a stub of os.homedir.                                       |\n| TESTKIT_ORG_USERNAME          | An org username to use for test commands. Tests will use this org rather than creating new orgs.                |\n| TESTKIT_PROJECT_DIR           | A SFDX project to use for testing. The tests will use this project directly rather than creating a new project. |\n| TESTKIT_SAVE_ARTIFACTS        | Prevents a test session from deleting orgs, projects, and test sessions during TestSession.clean().             |\n| TESTKIT_ENABLE_ZIP            | Allows zipping the session dir when this is true and `TestSession.zip()` is called during a test.               |\n| TESTKIT_SETUP_RETRIES         | Number of times to retry the setupCommands after the initial attempt before throwing an error.                  |\n| TESTKIT_SETUP_RETRIES_TIMEOUT | Milliseconds to wait before the next retry of setupCommands. Defaults to 5000.                                  |\n| TESTKIT_EXEC_SHELL            | The shell to use for all testkit shell executions rather than the shelljs default.                              |\n| TESTKIT_HUB_USERNAME          | Username of an existing, authenticated devhub org that TestSession will use to auto-authenticate for tests.     |\n| TESTKIT_JWT_CLIENT_ID         | clientId of the connected app that TestSession will use to auto-authenticate for tests.                         |\n| TESTKIT_JWT_KEY               | JWT key file **contents** that TestSession will use to auto-authenticate for tests.                             |\n| TESTKIT_HUB_INSTANCE          | Instance url for the devhub org. Defaults to https://login.salesforce.com                                       |\n| TESTKIT_AUTH_URL              | Auth url that TestSession will use to auto-authenticate for tests. Uses the `auth:sfdxurl:store` command.       |\n\n# Contributing\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesforcecli%2Fcli-plugins-testkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsalesforcecli%2Fcli-plugins-testkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsalesforcecli%2Fcli-plugins-testkit/lists"}