Testing

NAIDE has built-in test and assertion support, powered by Node.js node:test.

Writing Tests

test "addition works":
  assert 1 + 1 == 2

test "string concatenation":
  str result = "hello" + " world"
  assert result == "hello world"

Running Tests

$ naide test tests.naide

Or compile and run with Node.js test runner:

$ naide tests.naide -o tests.mjs
$ node --test tests.mjs

Assertions

The assert keyword maps to node:assert/strict:

assert 1 == 1           # strict equal
assert "a" != "b"       # not equal
assert list.length > 0  # truthy expression
assert result           # truthy check

Mock Functions

Create mock functions to track calls:

use {createMock} from "naider/runtime"

any mockFn = createMock()
mockFn("hello")
mockFn("world")

assert mockFn.callCount() == 2
assert mockFn.calledWith("hello")

# Set return value
mockFn.returns(42)
assert mockFn() == 42

# Wrap existing function
any mock = createMock((x) => x * 2)
assert mock(5) == 10

# Change implementation
mock.impl((x) => x + 1)
assert mock(5) == 6

# Reset all state
mock.reset()

Spies

Spy on object methods without replacing them:

use {createSpy} from "naider/runtime"

any obj = {greet: (name) => "hi " + name}
any spy = createSpy(obj, "greet")

obj.greet("world")
assert spy.callCount() == 1
assert spy.calledWith("world")

# Restore original method
spy.restore()

Testing Server Routes

test "GET / returns ok":
  # Compile and test with your HTTP testing library
  assert true

test "validates user input":
  use {createSchema, validateMiddleware} from "naider/runtime"
  any schema = createSchema("User", {name: {type: "string", required: true, min: 2}})
  any mid = validateMiddleware(schema)

  # Short name fails validation
  any req = {method: "POST", body: {name: "A"}}
  any res = {status: (c) => {return {json: (d) => null}}}
  bool called = false
  mid(req, res, () => {called = true})
  assert not called