API Maker

The framework for AI era

Team & delivery

Testing Framework

Test the business logic of your custom APIs and utility classes, inside API Maker.

A test case is TypeScript: a list of small tests, each an async function with node:assert. Mocks stand in for the database and system APIs, so a test checks your logic without touching real data. Run all of them, or the ones you pick, and see each result with the line that failed.

See it live

Step through it, slow it down, or open the full canvas.

api-maker/features/inbuilt-testingLive
  • Call
  • Mock
  • Passed
  • Failed
Tests
2in the case
Passed
0last run
Database calls
0mocked
Runs in
1the sandbox

Test cases live next to your code. A test case is TypeScript: an array of small tests, each with a name and an async function using node:assert. Import your utility classes and call them with g.

How it works

  1. Test cases live next to your code.

    A test case is TypeScript: an array of small tests, each with a name and an async function using node:assert. Import your utility classes and call them with g.

  2. Mocks stand in for the database.

    Pick an API method, here g.sys.db.query, the values its arguments must have and what it returns. A matching call gets that value, no database needed.

  3. They run in the sandbox.

    Each test calls your real code. The query is answered by the mock, the database is not called, and every assert is checked.

  4. Run them all, or the ones you pick.

    Execute runs every test of the test case you are on. Run lets you check the test cases you want. Each small test shows its own result.

  5. A change that breaks a rule is caught.

    Someone moves the discount threshold. The failing test shows the assert message and its line in your TypeScript, before anything is deployed.

What you get

Small tests, one file

A test case exports an array of { name, code } objects. Each code is an async function that gets g.

Mocks without a database

Pick a method like g.sys.db.query, the arguments it must receive and the value it returns. Matching calls get that value.

Your real code

Import your utility classes and call them as your APIs do. The test runs the same code the API runs.

Execute or pick

Execute runs every test of the test case you are on. Run lets you tick the tests you want.

Failures you can read

A failing test shows the assert message, the actual and expected values, and its line in your TypeScript.

Reviewed like code

Test cases go to Git with the rest of the project, so a pull request shows the tests next to the change.

An example

Catch a broken rule before release

Someone changes the discount threshold in a utility class. The test case fails with its message and line, before the change reaches a pull request.

A test case for a discount rulediscount.test.ts
import * as T from 'types';import * as assert from 'node:assert';import * as pricing from 'utils/Pricing';module.exports = [    {        name: 'No discount under 1000',        code: async (g: T.IAMGlobal) => {            assert.strictEqual(await pricing.discountFor(g, 999), 0);        },    },    {        name: '10% from 1000',        code: async (g: T.IAMGlobal) => {            assert.strictEqual(await pricing.discountFor(g, 1000), 100);        },    },];

Good to know

  • Calls that no mock matches reach the real API, so keep test data in mind when a test is not fully mocked.

Questions

Where do tests run?

In the sandbox, like your custom APIs.

Can I test an API end to end?

Yes, from the API testing page: send a request with any body and headers, read the response, and keep it as a saved state.