Client-side Testing¶
DGT-TST-030 — Unit-test the logic in TypeScript web resources
the same way you'd test any other TypeScript: with Jest, mocking the Xrm API via
xrm-mock. The
webresources-template ships the
tooling (Jest, ts-jest, jest-environment-jsdom, xrm-mock) as dependencies, but not
(yet) a jest.config.* or an example test — add the config below and at least one test file
yourself when you start a new project from the template.
What to test — and what not to¶
- Test your logic: branching in form/ribbon handlers, calculations, the decisions a handler makes given attribute values.
- Don't test the platform: that
addOnSaveregisters a handler, or thatgetAttributereturns a value, is Microsoft's code — mock it and assert on your behavior. - Factor non-trivial logic into plain functions that take inputs and return outputs; they're the
easiest thing to test and keep the
Xrm-bound handler thin.
Setup¶
Configure Jest to transform TypeScript with ts-jest and run in the jsdom environment:
export default {
preset: "ts-jest/presets/default-esm",
testEnvironment: "jsdom",
testMatch: ["**/*.test.ts"],
};
Run with the template's scripts — pnpm run test (once) or pnpm run test-watch.
Example: a form OnLoad handler¶
import { XrmMockGenerator } from "xrm-mock";
import { Account } from "./account.form";
describe("Account.onLoad", () => {
beforeEach(() => XrmMockGenerator.initialise());
it("requires the name when the account is active", () => {
const name = XrmMockGenerator.Attribute.createString("name", "");
const context = XrmMockGenerator.getEventContext();
Account.onLoad(context);
expect(name.getRequiredLevel()).toBe("required");
});
});
XrmMockGenerator.initialise() builds a fresh fake Xrm/form context per test, so cases stay
isolated — arrange the attributes and controls the handler reads, invoke the exported handler,
then assert on the resulting form state.
Where this runs¶
Client-side tests run in the Build Pipeline alongside the server-side unit tests — both gate the build before packaging. Treating a green client-side test run as part of the Definition of Done keeps form-script regressions out of a release the same way plugin tests do on the server side.