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.js is a one-line spread of the @nx/jest preset; each project's jest.config.ts applies it and sets displayName, transform (babel-jest with @nx/react/babel for UI projects, ts-jest where configured), and coverageDirectory.
  • The root jest.config.ts aggregates every project through getJestProjectsAsync(); it exists for IDE and whole-repo runs.
  • nx.json registers @nx/jest/plugin with targetName: "test", so any project containing a jest.config.* file gets an inferred test target. @nx/eslint/plugin similarly infers lint, and @nx/webpack/plugin infers build/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:

ProjectPathSpecs
erxes-api-sharedbackend/erxes-api-shared/src/** (core-modules/, utils/)27
core-uifrontend/core-ui/src/modules/**5
content_apibackend/plugins/content_api/src/modules/cms/postiz/__tests__/, test/5
content_uifrontend/plugins/content_ui/src/modules/cms/**4
sales_apibackend/plugins/sales_api/src/modules/pos/2
saas-migrationsbackend/saas-migrations/content/knowledgebase/__tests__/2
core-apibackend/core-api/src/modules/documents/__tests__/1
erxes-uifrontend/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 a test target set up end to end (jest.config.ts + explicit project.json target). The core-modules/segments/ specs alone show how to test a pure engine: evaluate.test.ts feeds 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.ts exercises 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 under nx test until the plugin adds a jest.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:

  1. Permissions and tenant isolation: a resolver or procedure that leaks another tenant's data is the worst regression; test the subdomain scoping, not just the happy path.
  2. Validation at the boundary: bad input rejected before it reaches the model layer.
  3. The behavior you changed: CONTRIBUTING.md asks 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:

  1. Reproduce the bug before fixing it, then confirm the same scenario passes.
  2. Exercise every state your change touches: loading, success, empty, and error.
  3. After each create, update, or delete, confirm the UI updates without a manual refresh (Apollo cache update, refetch, or subscribeToMore).
  4. 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.
  5. Re-run pnpm nx lint <project> and pnpm 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.

Was this helpful?