Skip to content

Gzingo/DMS-API-Tests

Repository files navigation

Document Management REST API — Test Suite

A Postman test suite for the DMS /wo/* REST API, with thin JavaScript helpers to run it and gate CI. This is a public showcase copy — please read the security note below.

About this project

A factory-QA test suite for the DMS document-management REST API (the /wo/* surface), built without access to the backend source code. The API was reverse-engineered from captured live HTTP traffic: during exploratory testing of the running application, requests were captured with Postman Interceptor, then replayed and shaped into a structured Postman collection, and each endpoint's contract was inferred from its observed responses (the running API treated as the contract of record). The suite spans ~246 requests across ~92 unique endpoints.

Tests are written from the end-user perspective and organized by discipline:

  • Smoke — reachability / basic health per endpoint.
  • E2E & E2E Workflows — per-module user journeys (CRUD, validation, business logic) and multi-step cross-module flows.
  • Contract — response-shape / error-envelope contracts (fail on contract drift, not business outcome).
  • Security — defensive controls (authentication, authorization, input validation, headers).
  • Security Fuzz — data-driven injection & robustness sweeps over a curated payload corpus.

Approach & test polarity

A core principle drives the design:

  • Test Objectivity — a test exists to reveal the system's real state, not to pass. Where the API misbehaves, the assertion is a RED-by-design marker that encodes a logged defect and stays red until it is fixed — never relaxed to make the run green.

ci-gate.mjs understands this: it fails the build only on an unexpected failure, so the defect markers don't break CI while a genuine regression does.

What it surfaced (categories)

Across the disciplines, the suite logged real issues spanning common security and robustness categories — e.g.:

  • Password-storage / hashing weaknesses.
  • Authentication & token-handling weaknesses.
  • Broken access control (object-level and role-based).
  • Missing brute-force / account-lockout protection.
  • Inconsistent error handling & contracts (e.g. 500-instead-of-4xx).

(Specifics — endpoints, reproduction, severities — are kept in the internal defect register, not in this public copy.)

Penetration testing (developed, deliberately not published)

Offensive proof-of-concept exploits were also written to confirm that several findings are genuinely exploitable end-to-end — not just theoretical — using an inverted-polarity model (the test passes when the exploit reproduces, so it doubles as a remediation-regression check). Those PoCs, and the exact exploit points they target, are intentionally withheld from this public repository for responsible-disclosure reasons. The defensive Security / Security Fuzz / Contract tests included here demonstrate the testing approach without shipping runnable exploits.

🔒 Security — no secrets in this repository

This repo ships no real credentials or secrets. The Postman environment is provided only as a scrubbed templatepostman/dms.postman_environment.example.json — with every secret value emptied. The real environment file (postman/dms.postman_environment.json, which would hold the login password and the JWT signing secret) is git-ignored and never committed.

Why this matters here in particular: that environment holds the JWT signing secret, and anyone who has it can forge authentication tokens for any user — which is, in fact, one of the very weaknesses this suite is built to demonstrate. A leaked password is straight account compromise. A public repository must never carry either. So the only environment in version control is the empty template; to actually run the suite you supply your own credentials locally (see "Providing credentials").

Layout

.                          # repo root
├── postman/
│   ├── dms.postman_collection.json            # the test suite (v2.1, _Parking stripped) — SOURCE OF TRUTH
│   └── dms.postman_environment.example.json   # env TEMPLATE — secret values EMPTY (copy + fill)
├── tests/                  # human-readable view of every request's test code (generated, read-only)
├── import-collection.mjs   # pull collection + env from Postman cloud (needs your own POSTMAN_API_KEY)
├── export-tests.mjs        # (re)generate tests/ from the collection
├── run-tests.mjs           # run discipline folders via Postman CLI -> reports/*.xml
├── ci-gate.mjs             # classify JUnit; fail ONLY on unexpected failures
├── package.json            # npm script shortcuts
└── reports/                # run artifacts (gitignored)

Reading the tests

The tests live inside the Postman collection (postman/dms.postman_collection.json) — that file is the single source of truth and the only thing that executes (locally and in CI). Because a collection is a large JSON file, the tests/ folder mirrors it as one readable .js per request (tests/<discipline>/<request>.js), showing the method/URL, the pre-request script, and the assertion (test) script. It is a generated, read-only view for browsing here on GitHub — nothing runs from it. Regenerate it after changing the collection with npm run export:tests.

The real postman/dms.postman_environment.json is git-ignored, so it is not present in a clone — you create it from the template.

Prerequisites

  • Node 18+.

  • Postman CLI (postman). Install it for your OS:

    npm run postman:install:linux   # Linux / CI
    npm run postman:install:mac     # macOS
    npm run postman:install:win     # Windows (PowerShell)
  • Postman login with your own key: postman login --with-api-key <YOUR_POSTMAN_API_KEY> (persists).

Providing credentials (required to actually run)

The repo contains no credentials, so first create your own local environment from the template:

cp postman/dms.postman_environment.example.json postman/dms.postman_environment.json

Then either fill the empty secret values in that copied file (edoc_authPassword, edoc_jwtSecret) and set edoc_baseUrl to your target server, or leave them empty and pass them as environment variables (EDOC_AUTH_PASSWORD, EDOC_JWT_SECRET, EDOC_BASE_URL) — run-tests.mjs overrides the file with those. The copied file is git-ignored, so your credentials stay on your machine and never get committed.

Run locally

All commands are npm scripts — run them from the repo root as npm run <name>. Each run writes JUnit to reports/; npm run gate then classifies it.

Run the whole gated set, then check the result:

npm run ci      # = run core (Smoke + Contract + Security + Security Fuzz) then gate; this is what CI does
npm run test    # just run the core (no gate)
npm run gate    # classify whatever is in reports/ and exit non-zero only on an UNEXPECTED failure

Run one Postman folder at a time (results accumulate in reports/, so run npm run gate after):

npm run test:setup         # Setup (token generation)
npm run test:smoke         # Smoke Tests
npm run test:e2e           # E2E Tests
npm run test:workflows     # E2E Workflows
npm run test:contract      # Contract Tests
npm run test:security      # Security Tests
npm run test:fuzz          # Security Fuzz Tests
npm run test:integration   # Integration Tests (empty placeholder — for future Flowable tests)
npm run test:performance   # Performance Tests (empty placeholder — for future k6/perf tests)

Other:

npm run test:all              # core + E2E + E2E Workflows (mutating, self-cleaning)
npm run import:postman:latest # pull the latest collection + env from Postman cloud

Ad-hoc — run any folder(s) without a named script via the underlying runner:

node run-tests.mjs --only "Contract Tests" --only "Security Tests"   # one or more folders
node ci-gate.mjs                                                    # gate the current reports/

The target server is set via edoc_baseUrl in your environment. A fresh run overwrites the matching reports/<folder>.xml; delete reports/ to start clean.

Test polarity & the CI gate (important)

The suite contains many RED-by-design markers — assertions that encode a real, logged defect (FND-xx / DEF-xx) and intentionally fail until the defect is fixed (Test Objectivity Policy: never relaxed to pass). A raw run therefore always reports failures. So:

  • run-tests.mjs runs with -x (don't abort on assertion failures) and writes JUnit per discipline.
  • ci-gate.mjs classifies every failure via a marker map (FND/DEF tag in the assertion name + per-request inheritance) and exits non-zero ONLY on an UNEXPECTED failure — a real regression. Known markers do not fail the build; a marker that stops failing is logged (defect likely fixed → update the register).

_Parking (Flowable BPM probes) is excluded entirely.

CI/CD

The runner + gate are CI-agnostic: install the Postman CLI, postman login, then npm run ci. The gate exit code is the build result (non-zero only on an UNEXPECTED failure). Note that this public copy ships no secrets, so any CI here would need credentials supplied out of band — by design, none are included.

Refreshing the suite from Postman

npm run import:postman:latest pulls the latest collection (drops _Parking) and environment from the cloud. It uses the Postman REST API (the CLI can run a collection but can't download one to a file), so it needs your own POSTMAN_API_KEY in the environment: POSTMAN_API_KEY=<key> npm run import:postman:latest. It writes the git-ignored real env file and keeps any secret values you already set there; the committed .example stays scrubbed.

About

QA test suite for a document-management REST API, reverse-engineered from captured HTTP traffic — Postman collection (E2E / contract / security / fuzz) + a marker-aware CI gate + a readable tests/ view.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors