39f3774940
统一 sources/templates/channels/rules 列表为分页响应,避免配置增多时全量返回;按钉钉 access_token 限制每分钟发送并在超限时等待下一分钟,降低触发官方封禁风险。 Co-authored-by: Cursor <cursoragent@cursor.com>
120 lines
3.7 KiB
Markdown
120 lines
3.7 KiB
Markdown
# 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>`.
|
||
|
||
1. **Create Source** — `POST /api/v1/sources`
|
||
- `parse_mode: json`, `status: 1`
|
||
- Capture `id`, `api_key`, `name`
|
||
|
||
2. **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`
|
||
|
||
3. **Create Template** — `POST /api/v1/templates`
|
||
- Content includes `{{.symbol}}` and `{{.price}}`
|
||
|
||
4. **Create Rule** — `POST /api/v1/rules`
|
||
- `source_name` / `template_name` / `channels` by name
|
||
- `event: trade.open`
|
||
- `enabled: 1`
|
||
- Conditions: `symbol` exists AND `price` gt `0`
|
||
|
||
5. **Notify** — `POST /api/v1/notify`
|
||
- `Authorization: Bearer <source.api_key>`
|
||
- Body: `{"event":"trade.open","data":{"symbol":"BTC","price":65000}}`
|
||
|
||
6. **Assert notify response**
|
||
- `matched == true`
|
||
- `accepted == true`
|
||
- `channels` length == 3
|
||
|
||
7. **Message-log check**
|
||
- Poll `GET /api/v1/message-logs?source=...&event=trade.open` for up to ~15s
|
||
- Assert at least one log entry appears (fail if none within timeout)
|
||
|
||
8. **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
|
||
|
||
```bash
|
||
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:
|
||
|
||
```make
|
||
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.
|