azure-devops-extension-mock
v1.0.2
Published
Jest mock for the Azure DevOps Extension SDK and REST API clients — no live Azure DevOps instance required.
Readme
azure-devops-extension-mock
Jest mock for the Azure DevOps Extension SDK and Azure DevOps Extension API. Lets you unit-test Azure DevOps web extensions without a live organization, project, or network.
Install
npm install --save-dev azure-devops-extension-mockThe package has no runtime dependencies. Requires Node.js 20.19 or newer.
Peer dependencies (you almost certainly already have them):
azure-devops-extension-api≥ 4azure-devops-extension-sdk≥ 4 (v5 supported)
The mocks themselves do not depend on any test framework. The Jest helpers
under jest-helpers/ target Jest 29 and 30.
Quick start
Mock the SDK by pointing jest's module resolver at it:
// jest.config.js
module.exports = {
preset: "ts-jest",
moduleNameMapper: {
"^azure-devops-extension-sdk$": "azure-devops-extension-mock/sdk",
},
};Use the REST client mocks in your tests via getClient:
import { getClient } from "azure-devops-extension-mock";
import { GitRestClient } from "azure-devops-extension-api/Git";
const git = getClient(GitRestClient);
const repos = await git.getRepositories();
expect(repos.length).toBeGreaterThan(0);Coverage
Every method of every REST client below is callable through getClient.
Hand-written methods return generated fixtures with the real signatures and
return types; the remaining methods resolve to undefined until you pin
them with overrides. Any other Azure DevOps client works the same way
through mockClient().
| Client | Hand-written | Stubbed | Total |
| --- | ---: | ---: | ---: |
| AccountsRestClient | 3 | 0 | 3 |
| WorkRestClient | 57 | 0 | 57 |
| BuildRestClient | 99 | 0 | 99 |
| CoreRestClient | 33 | 0 | 33 |
| DashboardRestClient | 13 | 0 | 13 |
| GitRestClient | 137 | 19 | 156 |
| PipelinesRestClient | 10 | 0 | 10 |
| ReleaseRestClient | 85 | 0 | 85 |
| TaskAgentRestClient | 110 | 48 | 158 |
| TestRestClient | 77 | 0 | 77 |
| WikiRestClient | 22 | 0 | 22 |
| WorkItemTrackingRestClient | 75 | 0 | 75 |
| All | 721 | 67 | 788 |
The table is generated by npm run surface, which reads the real .d.ts
declarations, and a test fails if a mock ever declares a method the real
client does not have.
Every export of the real SDK (init, ready, getUser, getHost,
getService, register, resize, tokens, theming, page/web/team/extension
context, sdkVersion, HostType, ...) is mocked in
azure-devops-extension-mock/sdk, plus the v5 enableNestedAppAuth and
disableNestedAppAuth.
API
getClient(realClientClass, overrides?)
Returns a mock instance for any Azure DevOps REST client class. Methods
with a hand-written mock return fixtures; every other method of the real
client resolves to undefined. No request is ever issued.
import { getClient } from "azure-devops-extension-mock";
import { BuildRestClient } from "azure-devops-extension-api/Build";
const build = getClient(BuildRestClient, {
queueBuild: async () => ({ id: 42, status: 2 } as any),
});
const result = await build.queueBuild({} as any, "MyProject");
expect(result.id).toBe(42);mockClient(realClientClass, overrides?, options?)
Lower-level factory used by getClient. Returns a Proxy that merges the
registered hand-written mock (if any) with the caller's overrides.
registerMockClient(realClientClass, MockClass)
Register a custom mock for a client not covered by this package. The
registered mock will be returned by all subsequent getClient calls.
getService(serviceId) / registerMockService(id, impl)
Mocks for CommonServiceIds.* services: extension data, host navigation,
page layout, location, global messages, project page. Register your own
for unknown ids.
getPageContext, getUser, getHost, …
Re-exported from azure-devops-extension-mock/sdk, matching the real SDK's
shape with randomly-generated fixture data.
Deterministic fixtures
Fixture data is random by default. Call seed to make a test run
reproducible:
import { fake } from "azure-devops-extension-mock/fixtures";
beforeEach(() => fake.seed(1234));Using with jest
Two things to wire up when testing an extension:
- Redirect the SDK import in
jest.config.js(moduleNameMapper). - If you use
azure-devops-extension-apiv4 and your tests import fromazure-devops-extension-api/*directly, add the AMD transformer that ships with this repo: v4 is published as AMD-only and jest needs help loading it under Node. v5 is CommonJS and needs no transform; the transformer returns v5 modules unchanged, so keeping it configured across an upgrade is harmless.
A ready-to-copy configuration:
// jest.config.js
module.exports = {
preset: "ts-jest",
moduleNameMapper: {
"^azure-devops-extension-sdk$": "azure-devops-extension-mock/sdk",
},
transform: {
"node_modules[\\\\/]azure-devops-extension-api[\\\\/].+\\.js$":
"azure-devops-extension-mock/jest-helpers/amd-transformer",
},
transformIgnorePatterns: ["node_modules/(?!azure-devops-extension-api)"],
setupFiles: ["azure-devops-extension-mock/jest-helpers/setup-globals"],
};Contributing
npm ci
npm test # runs jest with coverage (90% threshold enforced)
npm run build # emits dist/
npm run surface # compares the mocks with the real client declarations
npm run audit:prod # production dependency auditCI runs tests on Node 22 and 24 (node.js.yml), weekly npm audit and
Gitleaks scans (security.yml), and CodeQL through GitHub's default code
scanning setup.
Releasing
- Update the version in
package.jsonand move theUnreleasednotes inCHANGELOG.mdunder that version. - Merge to
main, then push a tag matching the version:git tag v1.2.3 && git push origin v1.2.3. release.ymlbuilds, tests, audits, publishes to npm with provenance via trusted publishing, and creates the GitHub release. No npm token is stored in the repository.
License
MIT — see license.
