Skip to content

Commit 796fc44

Browse files
feat(plugin-assert): add assertion plugin (#46)
1 parent 7e43a27 commit 796fc44

28 files changed

Lines changed: 1885 additions & 2 deletions

File tree

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Release Plugin Assert
2+
3+
on:
4+
push:
5+
tags:
6+
- "plugin-assert-v*.*.*"
7+
workflow_dispatch:
8+
inputs:
9+
dry-run:
10+
description: "Dry run (don't actually publish)"
11+
required: false
12+
type: boolean
13+
default: false
14+
15+
jobs:
16+
release:
17+
name: Build and Publish Plugin Assert
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
id-token: write
22+
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v4
26+
27+
- name: Extract version from tag
28+
id: version
29+
run: |
30+
if [[ "${{ github.event_name }}" == "push" ]]; then
31+
# Extract version from tag (plugin-assert-v1.2.3 -> 1.2.3)
32+
VERSION="${GITHUB_REF#refs/tags/plugin-assert-v}"
33+
else
34+
# For manual trigger, read from package.json
35+
VERSION=$(jq -r .version packages/plugins/assert/package.json)
36+
fi
37+
echo "version=$VERSION" >> $GITHUB_OUTPUT
38+
echo "Extracted version: $VERSION"
39+
40+
- name: Verify version matches package.json
41+
run: |
42+
PKG_VERSION=$(jq -r .version packages/plugins/assert/package.json)
43+
TAG_VERSION="${{ steps.version.outputs.version }}"
44+
if [[ "$PKG_VERSION" != "$TAG_VERSION" ]]; then
45+
echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PKG_VERSION)"
46+
echo "The tag must match the committed version. Ensure you've merged the Version Packages PR first."
47+
exit 1
48+
fi
49+
echo "Version verified: $PKG_VERSION"
50+
51+
- name: Setup Bun
52+
uses: oven-sh/setup-bun@v2
53+
with:
54+
bun-version-file: package.json
55+
56+
- name: Setup Node.js
57+
uses: actions/setup-node@v4
58+
with:
59+
node-version: "20"
60+
registry-url: "https://registry.npmjs.org"
61+
62+
- name: Install dependencies
63+
run: bun install --frozen-lockfile
64+
65+
- name: Verify publish manifest
66+
run: bun run script/verify-publish-manifest.ts packages/plugins/assert/package.json
67+
68+
- name: Build core (workspace dependency)
69+
run: bun run build
70+
working-directory: packages/core
71+
72+
- name: Build
73+
run: bun run build
74+
working-directory: packages/plugins/assert
75+
76+
- name: Check types
77+
run: bun run check-types
78+
working-directory: packages/plugins/assert
79+
80+
- name: Run tests
81+
run: bun run test
82+
working-directory: packages/plugins/assert
83+
84+
- name: Publish to npm
85+
if: ${{ github.event_name == 'push' || !inputs.dry-run }}
86+
run: npm publish --access public
87+
working-directory: packages/plugins/assert
88+
env:
89+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
90+
91+
- name: Dry run publish
92+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.dry-run }}
93+
run: |
94+
npm pack
95+
echo "[dry-run] Would publish @t-req/plugin-assert@${{ steps.version.outputs.version }}"
96+
working-directory: packages/plugins/assert

bun.lock

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"release:core": "bun run script/release.ts --package core",
1919
"release:sdk": "bun run script/release.ts --package sdk",
2020
"release:plugin-base": "bun run script/release.ts --package plugin-base",
21+
"release:plugin-assert": "bun run script/release.ts --package plugin-assert",
2122
"sst:dev": "sst dev",
2223
"sst:deploy": "sst deploy",
2324
"sst:deploy:prod": "sst deploy --stage production"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# @t-req/plugin-assert
2+
3+
## 0.1.0
4+
5+
### Features
6+
7+
- Initial release.
8+
- Runtime assertion evaluation for `# @assert ...` directives.
9+
- `treq validate` integration for assertion diagnostics.

packages/plugins/assert/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 tensorix labs
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/plugins/assert/README.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# @t-req/plugin-assert
2+
3+
Inline assertions for [t-req](https://github.com/tensorix-labs/t-req) using `# @assert ...` directives in `.http` files.
4+
5+
[![npm version](https://img.shields.io/npm/v/@t-req/plugin-assert.svg)](https://www.npmjs.com/package/@t-req/plugin-assert)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7+
8+
## Installation
9+
10+
```bash
11+
npm install @t-req/plugin-assert
12+
13+
# or
14+
bun add @t-req/plugin-assert
15+
yarn add @t-req/plugin-assert
16+
pnpm add @t-req/plugin-assert
17+
```
18+
19+
## Setup
20+
21+
Add to `treq.jsonc`:
22+
23+
```jsonc
24+
{
25+
"plugins": ["@t-req/plugin-assert"]
26+
}
27+
```
28+
29+
Or load ad-hoc:
30+
31+
```bash
32+
treq run ./requests/user.http --plugin @t-req/plugin-assert
33+
```
34+
35+
## Assertion Syntax
36+
37+
```http
38+
# @assert status == 200
39+
# @assert header Content-Type contains application/json
40+
# @assert body contains "ok"
41+
# @assert jsonpath $.token exists
42+
GET https://api.example.com/health
43+
```
44+
45+
Supported targets:
46+
47+
| Target | Operators | Example |
48+
|---|---|---|
49+
| `status` | `== != > >= < <=` | `# @assert status == 200` |
50+
| `header <name>` | `exists == != contains` | `# @assert header X-Trace-Id exists` |
51+
| `body` | `contains not-contains` | `# @assert body not-contains "error"` |
52+
| `jsonpath <expr>` | `exists == !=` | `# @assert jsonpath $.count == 2` |
53+
54+
## Behavior
55+
56+
- Assertions run in `response.after`.
57+
- One summary report is emitted per request with:
58+
- `kind: "assert"`
59+
- `passed: boolean`
60+
- `total`, `failed`
61+
- `checks[]` details
62+
- Any failed assertion sets `passed: false`, and `treq run` exits with code `1`.
63+
- Malformed assertions also fail the run (fail-fast behavior).
64+
65+
## Validate Integration
66+
67+
`treq validate` uses this plugin's `validate` hook to surface assertion issues early:
68+
69+
- `assert.syntax`
70+
- `assert.operator`
71+
- `assert.target`
72+
- `assert.missing-value`
73+
- `assert.invalid-jsonpath`
74+
- `assert.position`
75+
76+
Example:
77+
78+
```bash
79+
treq validate ./requests
80+
```
81+
82+
## License
83+
84+
MIT
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"name": "@t-req/plugin-assert",
3+
"version": "0.1.0",
4+
"description": "Inline assertion plugin for t-req (@assert directives in .http files)",
5+
"license": "MIT",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/tensorix-labs/t-req",
9+
"directory": "packages/plugins/assert"
10+
},
11+
"homepage": "https://github.com/tensorix-labs/t-req#readme",
12+
"bugs": {
13+
"url": "https://github.com/tensorix-labs/t-req/issues"
14+
},
15+
"keywords": [
16+
"t-req",
17+
"plugin",
18+
"assertions",
19+
"jsonpath",
20+
"http-testing"
21+
],
22+
"author": "tensorix labs",
23+
"engines": {
24+
"node": ">=18",
25+
"bun": ">=1.0.0"
26+
},
27+
"type": "module",
28+
"main": "dist/index.js",
29+
"types": "dist/index.d.ts",
30+
"exports": {
31+
".": {
32+
"types": "./dist/index.d.ts",
33+
"import": "./dist/index.js",
34+
"default": "./dist/index.js"
35+
}
36+
},
37+
"publishConfig": {
38+
"access": "public"
39+
},
40+
"files": [
41+
"dist",
42+
"README.md",
43+
"LICENSE"
44+
],
45+
"scripts": {
46+
"build": "bun run build:js && bun run build:types",
47+
"build:js": "bun build --target node --minify --sourcemap --outdir ./dist --root ./src ./src/index.ts",
48+
"build:types": "tsc -p tsconfig.build.json",
49+
"check-types": "tsc -p tsconfig.build.json --noEmit",
50+
"test": "bun test",
51+
"lint": "biome check .",
52+
"lint:fix": "biome check --write .",
53+
"prepublishOnly": "bun run build && bun run test"
54+
},
55+
"peerDependencies": {
56+
"@t-req/core": "^0.2.3"
57+
},
58+
"dependencies": {
59+
"fast-deep-equal": "^3.1.3",
60+
"jsonpath-plus": "^10.3.0"
61+
},
62+
"devDependencies": {
63+
"@t-req/core": "workspace:*",
64+
"@types/bun": "latest"
65+
}
66+
}

0 commit comments

Comments
 (0)