[PR #2807] Test api full suite #3167

Open
opened 2026-04-16 09:50:52 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/fosrl/pangolin/pull/2807
Author: @jbelke
Created: 4/7/2026
Status: 🔄 Open

Base: devHead: test-api-full-suite


📝 Commits (8)

📊 Changes

12 files changed (+3269 additions, -28 deletions)

View changed files

📝 package-lock.json (+955 -26)
📝 package.json (+6 -2)
test/bugs/identified-bugs.test.ts (+169 -0)
test/lib/ip.test.ts (+249 -0)
test/lib/passwordSchema.test.ts (+71 -0)
test/lib/sanitize.test.ts (+86 -0)
test/lib/utilities.test.ts (+86 -0)
test/lib/validators.test.ts (+279 -0)
test/schemas/auth.test.ts (+480 -0)
test/schemas/resource-org-site-role.test.ts (+488 -0)
test/schemas/user.test.ts (+361 -0)
vitest.config.ts (+39 -0)

📄 Description

Community Contribution License Agreement

By creating this pull request, I grant the project maintainers an unlimited,
perpetual license to use, modify, and redistribute these contributions under any terms they
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content.

Description

Adds a comprehensive Vitest-based API testing suite with 254 tests across 9 test files covering schema validation, utility/library functions, and bug regression documentation.

What's included

Schema validation tests (Zod):

  • Auth: login, signup, resetPassword, changePassword, requestTotpSecret, verifyTotp, disable2fa
  • User: inviteUser (role deduplication, validHours boundaries), acceptInvite, createOrgUser
  • Resource: HTTP resources (subdomain, stickySession, postAuthPath), raw resources (port range 1-65535)
  • Organization: orgId regex validation, CIDR subnet validation
  • Site: newt/wireguard/local type enum, exitNodeId, address
  • Role: SSH PAM fields, sshSudoMode enum, sshSudoCommands

All schema tests validate strictObject rejection of unexpected fields, email lowercasing, boundary conditions, and required vs. optional field behavior.

Library/utility tests:

  • validators — isValidCIDR, isValidIP, isValidDomain, isSecondLevelDomain, isValidUrlGlobPattern, isUrlValid, isTargetValid, validateHeaders
  • ip — cidrToRange, findNextAvailableCidr, isIpInCidr, doCidrsOverlap, parseEndpoint, formatEndpoint, portRangeStringSchema, parsePortRangeString
  • sanitize — null byte stripping, C0 control character removal, lone UTF-16 surrogate replacement
  • passwordSchema — all strength requirements (upper, lower, digit, special), min/max length boundaries
  • normalizePostAuthPath — open redirect prevention (//, : rejection), whitespace trimming
  • stoi — string-to-integer pass-through behavior

Bug regression tests documenting 6 issues found during code review:

# Severity File Issue
1 Low signup.ts:4 Unused email named import from zod — will break on Zod v4
2 Medium signup.ts:272 Only catches SqliteError for unique constraint — PostgreSQL duplicate signups get a 500 instead of "user already exists"
3 Low resetPassword.ts:174 Response type is ResetPasswordResponse but data: null is set on success
4 Low external.ts:970 Duplicate GET /idp/:idpId route registration (dead code)
5 Medium external.ts:1251-1284 2FA rate limiters (enable, request, disable) all use signup: key prefix — rate limit bucket collision
6 Medium external.ts:1235 Olm get-token rate limiter keys on req.body.newtId instead of req.body.olmId (copy-paste from newt endpoint)

These are documented as tests only; source fixes are intentionally deferred to a follow-up PR.

Infrastructure:

  • vitest.config.ts with v8 coverage provider and path aliases
  • package.json: added vitest devDependency, test, test:watch, test:coverage scripts

Design notes

  • Schema tests re-define Zod schemas inline rather than importing from handler files to avoid pulling in transitive config/db/session dependencies that require a running server
  • IP utility tests mock @server/lib/config, @server/db, and @server/logger at the module level since ip.ts imports them at top-level even though the tested functions are pure
  • No test touches the database, config files, email, or network — the entire suite runs in ~400ms

How to test?

# Run all tests
npm test

# Run with watch mode
npm run test:watch

# Run with coverage report
npm run test:coverage

# Verify build is unaffected
npm run build

Expected output:

 ✓ test/schemas/auth.test.ts (47 tests) 5ms
 ✓ test/schemas/user.test.ts (34 tests) 4ms
 ✓ test/schemas/resource-org-site-role.test.ts (42 tests) 6ms
 ✓ test/lib/validators.test.ts (50 tests) 8ms
 ✓ test/lib/ip.test.ts (37 tests) 4ms
 ✓ test/lib/sanitize.test.ts (12 tests) 1ms
 ✓ test/lib/passwordSchema.test.ts (12 tests) 1ms
 ✓ test/lib/utilities.test.ts (14 tests) 1ms
 ✓ test/bugs/identified-bugs.test.ts (6 tests) 2ms

 Test Files  9 passed (9)
      Tests  254 passed (254)

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/fosrl/pangolin/pull/2807 **Author:** [@jbelke](https://github.com/jbelke) **Created:** 4/7/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `test-api-full-suite` --- ### 📝 Commits (8) - [`1f74e1b`](https://github.com/fosrl/pangolin/commit/1f74e1b320b2a22c2f9f13af4e10893b6df24189) Merge pull request #2776 from fosrl/dev - [`16e7233`](https://github.com/fosrl/pangolin/commit/16e7233a3eaeae171312f154df8109b03c7ca3dc) Merge pull request #2777 from fosrl/dev - [`035644e`](https://github.com/fosrl/pangolin/commit/035644eaf767e4b50339f6d29892436f1c7eb6a5) Merge pull request #2778 from fosrl/dev - [`6ce165b`](https://github.com/fosrl/pangolin/commit/6ce165bfd5b20a0a63b4c170982d8d060825f472) Merge pull request #2780 from fosrl/dev - [`4b3375a`](https://github.com/fosrl/pangolin/commit/4b3375ab8e63c0028a004ee2b30f4a8381c63436) Merge pull request #2783 from fosrl/dev - [`3436105`](https://github.com/fosrl/pangolin/commit/3436105bec4ec3377dad3c0a8f2c2a3934a1f994) Merge pull request #2784 from fosrl/dev - [`da73b19`](https://github.com/fosrl/pangolin/commit/da73b19cacdab6fb8f79f9c0c276c2857c8e3341) test: add comprehensive API testing suite with 254 tests - [`39f86ed`](https://github.com/fosrl/pangolin/commit/39f86edae61320086a3f9091400321c92819f452) Merge branch 'fosrl:main' into test-api-full-suite ### 📊 Changes **12 files changed** (+3269 additions, -28 deletions) <details> <summary>View changed files</summary> 📝 `package-lock.json` (+955 -26) 📝 `package.json` (+6 -2) ➕ `test/bugs/identified-bugs.test.ts` (+169 -0) ➕ `test/lib/ip.test.ts` (+249 -0) ➕ `test/lib/passwordSchema.test.ts` (+71 -0) ➕ `test/lib/sanitize.test.ts` (+86 -0) ➕ `test/lib/utilities.test.ts` (+86 -0) ➕ `test/lib/validators.test.ts` (+279 -0) ➕ `test/schemas/auth.test.ts` (+480 -0) ➕ `test/schemas/resource-org-site-role.test.ts` (+488 -0) ➕ `test/schemas/user.test.ts` (+361 -0) ➕ `vitest.config.ts` (+39 -0) </details> ### 📄 Description ## Community Contribution License Agreement By creating this pull request, I grant the project maintainers an unlimited, perpetual license to use, modify, and redistribute these contributions under any terms they choose, including both the AGPLv3 and the Fossorial Commercial license terms. I represent that I have the right to grant this license for all contributed content. ## Description Adds a comprehensive Vitest-based API testing suite with **254 tests across 9 test files** covering schema validation, utility/library functions, and bug regression documentation. ### What's included **Schema validation tests (Zod):** - Auth: login, signup, resetPassword, changePassword, requestTotpSecret, verifyTotp, disable2fa - User: inviteUser (role deduplication, validHours boundaries), acceptInvite, createOrgUser - Resource: HTTP resources (subdomain, stickySession, postAuthPath), raw resources (port range 1-65535) - Organization: orgId regex validation, CIDR subnet validation - Site: newt/wireguard/local type enum, exitNodeId, address - Role: SSH PAM fields, sshSudoMode enum, sshSudoCommands All schema tests validate `strictObject` rejection of unexpected fields, email lowercasing, boundary conditions, and required vs. optional field behavior. **Library/utility tests:** - `validators` — isValidCIDR, isValidIP, isValidDomain, isSecondLevelDomain, isValidUrlGlobPattern, isUrlValid, isTargetValid, validateHeaders - `ip` — cidrToRange, findNextAvailableCidr, isIpInCidr, doCidrsOverlap, parseEndpoint, formatEndpoint, portRangeStringSchema, parsePortRangeString - `sanitize` — null byte stripping, C0 control character removal, lone UTF-16 surrogate replacement - `passwordSchema` — all strength requirements (upper, lower, digit, special), min/max length boundaries - `normalizePostAuthPath` — open redirect prevention (`//`, `:` rejection), whitespace trimming - `stoi` — string-to-integer pass-through behavior **Bug regression tests** documenting 6 issues found during code review: | # | Severity | File | Issue | |---|----------|------|-------| | 1 | Low | `signup.ts:4` | Unused `email` named import from `zod` — will break on Zod v4 | | 2 | Medium | `signup.ts:272` | Only catches `SqliteError` for unique constraint — PostgreSQL duplicate signups get a 500 instead of "user already exists" | | 3 | Low | `resetPassword.ts:174` | Response type is `ResetPasswordResponse` but `data: null` is set on success | | 4 | Low | `external.ts:970` | Duplicate `GET /idp/:idpId` route registration (dead code) | | 5 | Medium | `external.ts:1251-1284` | 2FA rate limiters (`enable`, `request`, `disable`) all use `signup:` key prefix — rate limit bucket collision | | 6 | Medium | `external.ts:1235` | Olm `get-token` rate limiter keys on `req.body.newtId` instead of `req.body.olmId` (copy-paste from newt endpoint) | These are documented as tests only; source fixes are intentionally deferred to a follow-up PR. **Infrastructure:** - `vitest.config.ts` with v8 coverage provider and path aliases - `package.json`: added `vitest` devDependency, `test`, `test:watch`, `test:coverage` scripts ### Design notes - Schema tests re-define Zod schemas inline rather than importing from handler files to avoid pulling in transitive config/db/session dependencies that require a running server - IP utility tests mock `@server/lib/config`, `@server/db`, and `@server/logger` at the module level since `ip.ts` imports them at top-level even though the tested functions are pure - No test touches the database, config files, email, or network — the entire suite runs in ~400ms ## How to test? ```bash # Run all tests npm test # Run with watch mode npm run test:watch # Run with coverage report npm run test:coverage # Verify build is unaffected npm run build ``` Expected output: ``` ✓ test/schemas/auth.test.ts (47 tests) 5ms ✓ test/schemas/user.test.ts (34 tests) 4ms ✓ test/schemas/resource-org-site-role.test.ts (42 tests) 6ms ✓ test/lib/validators.test.ts (50 tests) 8ms ✓ test/lib/ip.test.ts (37 tests) 4ms ✓ test/lib/sanitize.test.ts (12 tests) 1ms ✓ test/lib/passwordSchema.test.ts (12 tests) 1ms ✓ test/lib/utilities.test.ts (14 tests) 1ms ✓ test/bugs/identified-bugs.test.ts (6 tests) 2ms Test Files 9 passed (9) Tests 254 passed (254) ``` --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-16 09:50:52 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#3167