Testing
How tests run in erxes/erxes, which Community Edition projects can run them, and what to check manually before a pull request.
For the branch workflow, see Contribute to codebase.
How Jest is set up
jest.preset.jsis a one-line spread of the@nx/jestpreset; each project'sjest.config.tsapplies it and setsdisplayName, transform (babel-jestwith@nx/react/babelfor UI projects,ts-jestwhere configured), andcoverageDirectory.- The root
jest.config.tsaggregates every project throughgetJestProjectsAsync(); it exists for IDE and whole-repo runs. nx.jsonregisters@nx/jest/pluginwithtargetName: "test", so any project containing ajest.config.*file gets an inferredtesttarget.@nx/eslint/pluginsimilarly inferslint, and@nx/webpack/plugininfersbuild/serve/preview.
Project targets
In the Community Edition, eight projects have a Jest config and therefore expose pnpm nx test <project>: core-ui, erxes-ui, ui-modules, content_ui, frontline_ui, operation_ui, sales_ui on the frontend, and erxes-api-shared on the backend, the only one that also declares an explicit test target in project.json. (Enterprise Edition plugin projects have their own configs.)
Most backend plugins have no Jest setup at all: sales_api, core-api, and content_api have no jest.config.ts, so their spec files do not run under pnpm nx test. Always check project.json or run pnpm nx show project <name> instead of assuming a target exists.
pnpm nx show project sales_ui # list the project's targets
pnpm nx test erxes-api-shared # run one project's tests
pnpm nx test core-ui
pnpm nx affected -t test # tests for changed projects only
pnpm nx affected -t lint,build,test # the full affected check before a PR
Where tests live (CE)
Fifty-six spec/test files exist in the repo; these are the Community Edition ones:
| Project | Path | Specs |
|---|---|---|
erxes-api-shared | backend/erxes-api-shared/src/** (core-modules/, utils/) | 27 |
core-ui | frontend/core-ui/src/modules/** | 5 |
content_api | backend/plugins/content_api/src/modules/cms/postiz/__tests__/, test/ | 5 |
content_ui | frontend/plugins/content_ui/src/modules/cms/** | 4 |
sales_api | backend/plugins/sales_api/src/modules/pos/ | 2 |
saas-migrations | backend/saas-migrations/content/knowledgebase/__tests__/ | 2 |
core-api | backend/core-api/src/modules/documents/__tests__/ | 1 |
erxes-ui | frontend/libs/erxes-ui/src/modules/chat-viz/utils/ | 1 |
The rest belong to Enterprise plugin projects.
Representative specs
Three projects cover most of the useful patterns:
erxes-api-shared: the deepest suite in the repo, and the only backend project with atesttarget set up end to end (jest.config.ts+ explicitproject.jsontarget). Thecore-modules/segments/specs alone show how to test a pure engine:evaluate.test.tsfeeds segment definitions through the evaluator and asserts membership, with no MongoDB involved. Start here for backend logic.core-ui: five specs over pure utility modules.src/modules/navigation/utils/pinnedNavigationActivities.spec.tsexercises the navigation helpers with plain inputs and outputs. The frontend pattern is the same: pick a pure function, feed it states, assert outputs.sales_api: two specs (modules/pos/fieldUtils.spec.ts,modules/pos/meta/automations/resolvers/resolvePosOrderPaymentUrl.spec.ts) that exist without a project Jest config. They are dormant: readable as patterns, not runnable undernx testuntil the plugin adds ajest.config.ts.
content_api is the fourth pattern and the exception: its Postiz specs run through jest.postiz.cjs, a standalone ts-jest config that matches only src/modules/cms/postiz/__tests__/*.spec.ts, outside the Nx target system entirely. test/dockerfile.test.cjs is a node:test contract test asserting the Dockerfile's NODE_OPTIONS=--jitless workaround stays in the installer stage. Its validation commands:
pnpm nx build content_api
node --test backend/plugins/content_api/test/dockerfile.test.cjs
pnpm exec tsc --noEmit -p backend/plugins/content_api/tsconfig.json
pnpm exec jest --config backend/plugins/content_api/jest.postiz.cjs --runInBand
saas-migrations uses yet another runner: tsx --test (npm run test:knowledgebase), the Node built-in runner rather than Jest.
What to cover
Co-locate specs under __tests__/. Backend service/model tests build tenant models with generateModels('test') and clean up in afterEach; frontend tests use @testing-library/react with Apollo's MockedProvider. Keep tests deterministic, isolated, and focused on behavior rather than implementation.
Whatever the module, the priorities are the same:
- Permissions and tenant isolation: a resolver or procedure that leaks another tenant's data is the worst regression; test the
subdomainscoping, not just the happy path. - Validation at the boundary: bad input rejected before it reaches the model layer.
- The behavior you changed:
CONTRIBUTING.mdasks for a test whenever the contribution adds observable behavior that is not already covered; a regression spec for a bug fix is worth more than a broad suite.
Manual verification checklist
Automated coverage is thin in most plugins, so CONTRIBUTING.md expects manual flows:
- Reproduce the bug before fixing it, then confirm the same scenario passes.
- Exercise every state your change touches: loading, success, empty, and error.
- After each create, update, or delete, confirm the UI updates without a manual refresh (Apollo cache update, refetch, or
subscribeToMore). - For widget and portal flows, test a fresh session, a reload, and a mobile viewport, and confirm no credentials leak into the URL or storage.
- Re-run
pnpm nx lint <project>andpnpm nx build <project>after review feedback, and record any check you could not run (with the reason) instead of describing it as passed.
Attach screenshots or recordings to the PR for any visible UI change.