统一 sources/templates/channels/rules 列表为分页响应,避免配置增多时全量返回;按钉钉 access_token 限制每分钟发送并在超限时等待下一分钟,降低触发官方封禁风险。 Co-authored-by: Cursor <cursoragent@cursor.com>
3.7 KiB
Remote E2E Notify Flow Test Design
Date: 2026-08-01
Status: Approved (pending final user review of this doc)
Goal
Add a Go end-to-end test that hits a deployed notification service over HTTP and exercises the full configuration → send path:
source → channel(s) → template → rule → POST /notify
Channels under test: DingTalk, Bark, Email. Real notifications are sent.
Non-goals
- Local
httptest/ in-process server tests - Mocking
ChannelSender - CI by default (opt-in via build tag + env vars)
- Committing secrets to the repo
Placement
| Item | Path |
|---|---|
| Test | test/e2e/notify_flow_test.go |
| Build tag | //go:build e2e |
| Make target | test-e2e (optional helper) |
Default make test / go test ./internal/... must not run this suite.
Target environment
| Setting | Default / source |
|---|---|
| Base URL | E2E_BASE_URL → default http://82.157.251.93:8080 |
| Admin auth | E2E_ADMIN_KEY → default admin-sk-change-me |
Required env vars (channels)
If any of these are missing, the test Skips (does not fail):
| Variable | Purpose |
|---|---|
E2E_DINGTALK_WEBHOOK |
DingTalk robot webhook URL |
E2E_DINGTALK_SECRET |
DingTalk sign secret |
E2E_BARK_URL |
Bark base URL, e.g. https://api.day.app/<device_key> |
E2E_EMAIL_TO |
Email recipient |
Secrets live only in the runner environment / local shell, never in source or this spec.
Flow
Resource names use a unique suffix (unix timestamp or random) to avoid collisions, e.g. e2e-src-<suffix>.
-
Create Source —
POST /api/v1/sourcesparse_mode: json,status: 1- Capture
id,api_key,name
-
Create Channels —
POST /api/v1/channels×3- DingTalk:
type=dingtalk, config{webhook_url, secret} - Bark:
type=bark, config{url} - Email:
type=email, config{to: [E2E_EMAIL_TO]} - All
status: 1
- DingTalk:
-
Create Template —
POST /api/v1/templates- Content includes
{{.symbol}}and{{.price}}
- Content includes
-
Create Rule —
POST /api/v1/rulessource_name/template_name/channelsby nameevent: trade.openenabled: 1- Conditions:
symbolexists ANDpricegt0
-
Notify —
POST /api/v1/notifyAuthorization: Bearer <source.api_key>- Body:
{"event":"trade.open","data":{"symbol":"BTC","price":65000}}
-
Assert notify response
matched == trueaccepted == truechannelslength == 3
-
Message-log check
- Poll
GET /api/v1/message-logs?source=...&event=trade.openfor up to ~15s - Assert at least one log entry appears (fail if none within timeout)
- Poll
-
Cleanup via
t.Cleanup(reverse order)- Delete rule → template → channels → source
- Cleanup errors: log only, do not fail the test after a successful assertion path
Run command
E2E_DINGTALK_WEBHOOK='...' \
E2E_DINGTALK_SECRET='...' \
E2E_BARK_URL='https://api.day.app/<device_key>' \
E2E_EMAIL_TO='149516886@qq.com' \
go test -tags e2e ./test/e2e/ -v -count=1 -timeout 2m
Optional Makefile:
test-e2e:
go test -tags e2e ./test/e2e/ -v -count=1 -timeout 2m
Implementation notes
- Use
net/http+encoding/json(stdlib); no new test deps required. - Helper for admin JSON requests and source-authed notify.
- Failures must include HTTP status + response body for debugging.
- Do not hardcode channel secrets in the test file.
Success criteria
- With env vars set and remote healthy: test passes; DingTalk, Bark, and Email receive a message.
- Without channel env vars: test skips cleanly.
- Without
-tags e2e: suite is not compiled/run.