Add an automated VM test against a real Invoice Ninja instance
CI / test (push) Canceled after 0s
CI / Build on the declared MSRV (push) Canceled after 0s
CI / Latest stable (advisory) (push) Canceled after 0s

Adds an invoiceninja-nixos flake input and two things built from it:

- nixosConfigurations.invoiceninja-test-nginx/-caddy: manual test
  VMs, re-exported as-is from that repo rather than redefined here —
  same principle as this crate being a client of the SDK, not a
  second implementation of it.
- checks.invoiceninja-cli: an automated nixosTest (tests/, adapted
  from invoiceninja-nixos's own test scaffolding) that boots a real
  Invoice Ninja instance and runs the actual invoiceninja-cli binary
  against it - create/list/get/update/invoice/payment/delete across
  clients, invoices, and payments - rather than raw curl.

tests/common.nix's module import had to change from a relative
../nixos-module/invoiceninja.nix (which doesn't exist here) to a
parameter threaded from the flake input's nixosModules.invoiceninja.

Building the VM pulls from the invoiceninja-nixos cachix cache via a
nixConfig block, mirroring that repo's own.

Also fixes a wrong assumption the first version of this test's final
assertion made, caught by actually running it against a real server:
`clients list` with no `--status` does not exclude soft-deleted
records - confirmed empirically (Invoice Ninja returns everything
regardless of is_deleted unless status=active is passed explicitly).
Corrected the test to check is_deleted via `clients get` instead, and
fixed the misleadingly-incomplete --status doc comment in cli.rs that
had the same wrong assumption baked in.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-26 16:57:46 -04:00
co-authored by Claude Sonnet 5
parent 96fba9a303
commit c8a67b1208
10 changed files with 466 additions and 4 deletions
+49
View File
@@ -112,6 +112,55 @@ The `test` and `msrv` jobs skip scheduled runs (`if: github.event_name !=
'schedule'`) — a pinned toolchain against a locked dependency graph can't
change on a timer, so the weekly run is for `stable` only.
### Testing against a real server
`flake.nix` has an `invoiceninja-nixos` input (Gitea, same host as this
repo's own remote) and re-exports two of its `nixosConfigurations` as
`invoiceninja-test-nginx`/`invoiceninja-test-caddy` — real NixOS VMs
running actual Invoice Ninja (PHP/Laravel + MariaDB + Redis + chromium for
PDF generation), not a mock. Reused as-is rather than redefined here, same
principle as this crate being a client of the SDK rather than a second
implementation of it — see that repo's own `CLAUDE.md` for what's actually
inside.
```sh
nix build --accept-flake-config '.#nixosConfigurations.invoiceninja-test-nginx.config.system.build.vm'
QEMU_NET_OPTS="hostfwd=tcp::8080-:80" ./result/bin/run-nixos-vm
```
`--accept-flake-config` is what lets the `nixConfig` cachix substituter
declared at the top of this file actually get used — without it (or if the
daemon's `trusted-users` rejects it anyway, which it did when scripted
through an agent sandbox in practice — built fine regardless, just slower)
Nix silently falls back to building from source. `QEMU_NET_OPTS` forwards
the guest's port 80 to host `8080`; it's a runtime flag to the generated
`run-nixos-vm` script, not baked into the VM config, so it has to be set on
every boot.
The VM has one fixed admin account baked in by the upstream repo's own test
fixtures (`admin@email.com` / `password`, from its `tests/invoice_ninja_test_password`) —
not meant to be secret, since it only ever exists inside a throwaway local
VM. There's no standing API token to copy anywhere; get one fresh each boot
via `/api/v1/login` (the SDK and CLI only ever use API-token auth, never
this login endpoint themselves — it's purely a test-fixture bootstrap
step):
```sh
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/login \
-H 'Content-Type: application/json' \
-d '{"email":"admin@email.com","password":"password"}' \
| jq -r '.data[0].token.token')
IN_API_TOKEN="$TOKEN" IN_BASE_URL=http://localhost:8080/api/v1 \
cargo run -- clients list
```
`jq` is in this flake's `devShells.default` for exactly this. There's also
an automated check (`checks.invoiceninja-cli` in `flake.nix`, backed by
`tests/`) that boots the same kind of VM and runs this CLI's own binary
against it non-interactively — see `tests/nixos-test.nix` for exactly what
it exercises. Verified working end to end (boot → login → token →
`clients create`/`list`) as of writing.
## Common commands
```sh