@kirrosh/apitool 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +27 -0
- package/.github/workflows/release.yml +97 -0
- package/.mcp.json +9 -0
- package/APITOOL.md +195 -0
- package/BACKLOG.md +62 -0
- package/CHANGELOG.md +88 -0
- package/LICENSE +21 -0
- package/README.md +105 -0
- package/bun.lock +291 -0
- package/docs/GLOSSARY.md +182 -0
- package/docs/INDEX.md +21 -0
- package/docs/agent.md +135 -0
- package/docs/archive/APITOOL-pre-M22.md +831 -0
- package/docs/archive/BACKLOG-AI-NATIVE.md +56 -0
- package/docs/archive/M1-M2-parser-runner.md +216 -0
- package/docs/archive/M4-M7-reporter-cli.md +179 -0
- package/docs/archive/M5-M7-storage-junit.md +300 -0
- package/docs/archive/M6-webui.md +339 -0
- package/docs/ci.md +274 -0
- package/docs/generation-issues.md +67 -0
- package/generated/.env.yaml +3 -0
- package/install.ps1 +80 -0
- package/install.sh +113 -0
- package/package.json +46 -0
- package/scripts/run-mocked-tests.ts +45 -0
- package/seed-demo.ts +53 -0
- package/self-tests/auth.yaml +18 -0
- package/self-tests/collections-crud.yaml +46 -0
- package/self-tests/environments-crud.yaml +48 -0
- package/self-tests/export.yaml +32 -0
- package/self-tests/runs.yaml +16 -0
- package/src/bun-types.d.ts +5 -0
- package/src/cli/commands/add-api.ts +51 -0
- package/src/cli/commands/ai-generate.ts +106 -0
- package/src/cli/commands/chat.ts +43 -0
- package/src/cli/commands/ci-init.ts +126 -0
- package/src/cli/commands/collections.ts +41 -0
- package/src/cli/commands/coverage.ts +65 -0
- package/src/cli/commands/doctor.ts +127 -0
- package/src/cli/commands/envs.ts +218 -0
- package/src/cli/commands/init.ts +84 -0
- package/src/cli/commands/mcp.ts +16 -0
- package/src/cli/commands/run.ts +137 -0
- package/src/cli/commands/runs.ts +108 -0
- package/src/cli/commands/serve.ts +22 -0
- package/src/cli/commands/update.ts +142 -0
- package/src/cli/commands/validate.ts +18 -0
- package/src/cli/index.ts +500 -0
- package/src/cli/output.ts +24 -0
- package/src/cli/runtime.ts +7 -0
- package/src/core/agent/agent-loop.ts +116 -0
- package/src/core/agent/context-manager.ts +41 -0
- package/src/core/agent/system-prompt.ts +33 -0
- package/src/core/agent/tools/diagnose-failure.ts +51 -0
- package/src/core/agent/tools/explore-api.ts +40 -0
- package/src/core/agent/tools/index.ts +48 -0
- package/src/core/agent/tools/manage-environment.ts +40 -0
- package/src/core/agent/tools/query-results.ts +40 -0
- package/src/core/agent/tools/run-tests.ts +38 -0
- package/src/core/agent/tools/send-request.ts +44 -0
- package/src/core/agent/tools/validate-tests.ts +23 -0
- package/src/core/agent/types.ts +22 -0
- package/src/core/generator/ai/ai-generator.ts +61 -0
- package/src/core/generator/ai/llm-client.ts +159 -0
- package/src/core/generator/ai/output-parser.ts +307 -0
- package/src/core/generator/ai/prompt-builder.ts +153 -0
- package/src/core/generator/ai/types.ts +56 -0
- package/src/core/generator/coverage-scanner.ts +87 -0
- package/src/core/generator/data-factory.ts +115 -0
- package/src/core/generator/index.ts +10 -0
- package/src/core/generator/openapi-reader.ts +142 -0
- package/src/core/generator/schema-utils.ts +52 -0
- package/src/core/generator/serializer.ts +189 -0
- package/src/core/generator/types.ts +47 -0
- package/src/core/parser/filter.ts +14 -0
- package/src/core/parser/index.ts +21 -0
- package/src/core/parser/schema.ts +175 -0
- package/src/core/parser/types.ts +50 -0
- package/src/core/parser/variables.ts +146 -0
- package/src/core/parser/yaml-parser.ts +85 -0
- package/src/core/reporter/console.ts +175 -0
- package/src/core/reporter/index.ts +23 -0
- package/src/core/reporter/json.ts +9 -0
- package/src/core/reporter/junit.ts +78 -0
- package/src/core/reporter/types.ts +12 -0
- package/src/core/runner/assertions.ts +172 -0
- package/src/core/runner/execute-run.ts +75 -0
- package/src/core/runner/executor.ts +150 -0
- package/src/core/runner/http-client.ts +69 -0
- package/src/core/runner/index.ts +12 -0
- package/src/core/runner/types.ts +48 -0
- package/src/core/setup-api.ts +97 -0
- package/src/core/utils.ts +9 -0
- package/src/db/queries.ts +868 -0
- package/src/db/schema.ts +215 -0
- package/src/mcp/server.ts +47 -0
- package/src/mcp/tools/ci-init.ts +57 -0
- package/src/mcp/tools/coverage-analysis.ts +58 -0
- package/src/mcp/tools/explore-api.ts +84 -0
- package/src/mcp/tools/generate-missing-tests.ts +80 -0
- package/src/mcp/tools/generate-tests-guide.ts +353 -0
- package/src/mcp/tools/manage-environment.ts +123 -0
- package/src/mcp/tools/manage-server.ts +87 -0
- package/src/mcp/tools/query-db.ts +141 -0
- package/src/mcp/tools/run-tests.ts +66 -0
- package/src/mcp/tools/save-test-suite.ts +164 -0
- package/src/mcp/tools/send-request.ts +53 -0
- package/src/mcp/tools/setup-api.ts +49 -0
- package/src/mcp/tools/validate-tests.ts +42 -0
- package/src/tui/chat-ui.ts +150 -0
- package/src/web/routes/api.ts +234 -0
- package/src/web/routes/dashboard.ts +348 -0
- package/src/web/routes/runs.ts +64 -0
- package/src/web/schemas.ts +121 -0
- package/src/web/server.ts +134 -0
- package/src/web/static/htmx.min.js +1 -0
- package/src/web/static/style.css +265 -0
- package/src/web/views/layout.ts +46 -0
- package/src/web/views/results.ts +209 -0
- package/tests/agent/agent-loop.test.ts +61 -0
- package/tests/agent/context-manager.test.ts +59 -0
- package/tests/agent/system-prompt.test.ts +42 -0
- package/tests/agent/tools/diagnose-failure.test.ts +85 -0
- package/tests/agent/tools/explore-api.test.ts +59 -0
- package/tests/agent/tools/manage-environment.test.ts +78 -0
- package/tests/agent/tools/query-results.test.ts +77 -0
- package/tests/agent/tools/run-tests.test.ts +89 -0
- package/tests/agent/tools/send-request.test.ts +78 -0
- package/tests/agent/tools/validate-tests.test.ts +59 -0
- package/tests/ai/ai-generator.integration.test.ts +131 -0
- package/tests/ai/llm-client.test.ts +145 -0
- package/tests/ai/output-parser.test.ts +132 -0
- package/tests/ai/prompt-builder.test.ts +67 -0
- package/tests/ai/types.test.ts +55 -0
- package/tests/cli/args.test.ts +63 -0
- package/tests/cli/chat.test.ts +38 -0
- package/tests/cli/ci-init.test.ts +112 -0
- package/tests/cli/commands.test.ts +316 -0
- package/tests/cli/coverage.test.ts +58 -0
- package/tests/cli/doctor.test.ts +39 -0
- package/tests/cli/envs.test.ts +181 -0
- package/tests/cli/init.test.ts +80 -0
- package/tests/cli/runs.test.ts +94 -0
- package/tests/cli/safe-run.test.ts +103 -0
- package/tests/cli/update.test.ts +32 -0
- package/tests/core/generator/schema-utils.test.ts +108 -0
- package/tests/core/parser/nested-assertions.test.ts +80 -0
- package/tests/core/runner/root-body-assertions.test.ts +70 -0
- package/tests/db/chat-queries.test.ts +88 -0
- package/tests/db/chat-schema.test.ts +37 -0
- package/tests/db/environments.test.ts +131 -0
- package/tests/db/queries.test.ts +409 -0
- package/tests/db/schema.test.ts +141 -0
- package/tests/fixtures/.env.yaml +3 -0
- package/tests/fixtures/auth-token-test.yaml +8 -0
- package/tests/fixtures/bail/suite-a.yaml +6 -0
- package/tests/fixtures/bail/suite-b.yaml +6 -0
- package/tests/fixtures/crud.yaml +35 -0
- package/tests/fixtures/invalid-missing-name.yaml +5 -0
- package/tests/fixtures/invalid-no-method.yaml +6 -0
- package/tests/fixtures/petstore-auth.json +295 -0
- package/tests/fixtures/petstore-simple.json +151 -0
- package/tests/fixtures/post-only.yaml +12 -0
- package/tests/fixtures/simple.yaml +6 -0
- package/tests/fixtures/valid/.env.yaml +1 -0
- package/tests/fixtures/valid/a.yaml +5 -0
- package/tests/fixtures/valid/b.yml +5 -0
- package/tests/generator/coverage-scanner.test.ts +129 -0
- package/tests/generator/data-factory.test.ts +133 -0
- package/tests/generator/openapi-reader.test.ts +131 -0
- package/tests/integration/auth-flow.test.ts +217 -0
- package/tests/mcp/coverage-analysis.test.ts +64 -0
- package/tests/mcp/explore-api-schemas.test.ts +105 -0
- package/tests/mcp/explore-api.test.ts +49 -0
- package/tests/mcp/generate-missing-tests.test.ts +69 -0
- package/tests/mcp/manage-environment.test.ts +89 -0
- package/tests/mcp/save-test-suite.test.ts +116 -0
- package/tests/mcp/send-request.test.ts +79 -0
- package/tests/mcp/setup-api.test.ts +106 -0
- package/tests/mcp/tools.test.ts +248 -0
- package/tests/parser/schema.test.ts +134 -0
- package/tests/parser/variables.test.ts +227 -0
- package/tests/parser/yaml-parser.test.ts +69 -0
- package/tests/reporter/console.test.ts +256 -0
- package/tests/reporter/json.test.ts +98 -0
- package/tests/reporter/junit.test.ts +284 -0
- package/tests/runner/assertions.test.ts +262 -0
- package/tests/runner/executor.test.ts +310 -0
- package/tests/runner/http-client.test.ts +138 -0
- package/tests/web/routes.test.ts +160 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# BACKLOG — AI-Native API Testing Strategy (Archived)
|
|
2
|
+
|
|
3
|
+
> Archived: all milestones M22-M27 completed. See BACKLOG.md for current backlog.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## M22: MCP-First Smart Test Generation ✅ DONE
|
|
8
|
+
|
|
9
|
+
- `generate_tests_guide` tool — полная API-спека + алгоритм генерации + YAML format reference
|
|
10
|
+
- `save_test_suite` tool — парсит YAML, валидирует через Zod, сохраняет
|
|
11
|
+
- `explore_api` enhanced — `includeSchemas: true` → request/response schemas
|
|
12
|
+
- `schema-utils.ts` — `compressSchema()`, `formatParam()`
|
|
13
|
+
- Удалён `list_environments` (дубликат `manage_environment`)
|
|
14
|
+
|
|
15
|
+
## M23: Runner Improvements + MCP Refinements ✅ DONE
|
|
16
|
+
|
|
17
|
+
- Nested body assertions — `flattenBodyAssertions` preprocessor
|
|
18
|
+
- Root body assertions (`_body`) — `_body: { type: "array" }`, `_body.length: { gt: 0 }`
|
|
19
|
+
- `setup_api` MCP tool
|
|
20
|
+
- `generate_missing_tests` MCP tool
|
|
21
|
+
- Исправлен `z.record()` баг (MCP SDK 1.27.1)
|
|
22
|
+
- int64 workaround документирован
|
|
23
|
+
|
|
24
|
+
## M24: Tags + Description Support ✅ DONE
|
|
25
|
+
|
|
26
|
+
- `tags: string[]` и `description: string` в TestSuite
|
|
27
|
+
- `filterSuitesByTags()` — OR logic, case-insensitive
|
|
28
|
+
- CLI `--tag` флаг (repeatable, comma-separated)
|
|
29
|
+
- MCP `run_tests` — параметр `tag: string[]`
|
|
30
|
+
- Console reporter — отображение тегов
|
|
31
|
+
|
|
32
|
+
## M25: MCP + CLI Cleanup ✅ DONE
|
|
33
|
+
|
|
34
|
+
- `query_db` — consolidated 4 tools into 1 (list_collections, list_runs, get_run_results, diagnose_failure)
|
|
35
|
+
- Deleted dead code (`list-environments.ts`)
|
|
36
|
+
- Removed `request` CLI command
|
|
37
|
+
|
|
38
|
+
## M26: WebUI Simplification ✅ DONE
|
|
39
|
+
|
|
40
|
+
- Single-page dashboard: collection selector → env → Run Tests → results + coverage + history
|
|
41
|
+
- Removed 8 routes, extracted shared views
|
|
42
|
+
- JUnit XML + JSON export buttons
|
|
43
|
+
|
|
44
|
+
## M27: CI/CD Integration (partial) ✅ DONE
|
|
45
|
+
|
|
46
|
+
- `apitool ci init` CLI command (GitHub Actions, GitLab CI)
|
|
47
|
+
- `ci_init` MCP tool with `dir` param
|
|
48
|
+
- Templates: permissions, continue-on-error, publish-unit-test-result-action, repository_dispatch
|
|
49
|
+
- Agent hints: run_tests, save_test_suite, generate_tests_guide suggest CI after tests pass
|
|
50
|
+
- `docs/ci.md` — guide with triggers, secrets, examples
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Стратегия и принципы
|
|
55
|
+
|
|
56
|
+
Перенесены в APITOOL.md.
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
> **Исторический snapshot** на момент реализации M1+M2. Актуальная документация — [APITOOL.md](../../APITOOL.md)
|
|
2
|
+
|
|
3
|
+
# M1: Parser + M2: Runner
|
|
4
|
+
|
|
5
|
+
Модули парсинга YAML-тестов и их выполнения.
|
|
6
|
+
|
|
7
|
+
## Быстрый старт
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add zod
|
|
11
|
+
bun test
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Программный запуск:
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { parseFile } from "./src/core/parser/index.ts";
|
|
18
|
+
import { runSuite } from "./src/core/runner/index.ts";
|
|
19
|
+
|
|
20
|
+
const suite = await parseFile("examples/jsonplaceholder.yaml");
|
|
21
|
+
const result = await runSuite(suite);
|
|
22
|
+
|
|
23
|
+
console.log(`${result.passed}/${result.total} passed`);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## YAML-формат тестов
|
|
27
|
+
|
|
28
|
+
### Минимальный пример
|
|
29
|
+
|
|
30
|
+
```yaml
|
|
31
|
+
name: Health Check
|
|
32
|
+
tests:
|
|
33
|
+
- name: "API is alive"
|
|
34
|
+
GET: /health
|
|
35
|
+
expect:
|
|
36
|
+
status: 200
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Полный пример (CRUD-цепочка с captures)
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
name: Users CRUD
|
|
43
|
+
base_url: "{{base}}"
|
|
44
|
+
headers:
|
|
45
|
+
Authorization: "Bearer {{token}}"
|
|
46
|
+
Content-Type: application/json
|
|
47
|
+
|
|
48
|
+
config:
|
|
49
|
+
timeout: 10000
|
|
50
|
+
retries: 1
|
|
51
|
+
retry_delay: 1000
|
|
52
|
+
|
|
53
|
+
tests:
|
|
54
|
+
- name: "Create user"
|
|
55
|
+
POST: /users
|
|
56
|
+
json:
|
|
57
|
+
name: "{{$randomName}}"
|
|
58
|
+
email: "{{$randomEmail}}"
|
|
59
|
+
expect:
|
|
60
|
+
status: 201
|
|
61
|
+
body:
|
|
62
|
+
id: { capture: user_id, type: integer }
|
|
63
|
+
name: { type: string }
|
|
64
|
+
duration: 2000
|
|
65
|
+
|
|
66
|
+
- name: "Get created user"
|
|
67
|
+
GET: /users/{{user_id}}
|
|
68
|
+
expect:
|
|
69
|
+
status: 200
|
|
70
|
+
body:
|
|
71
|
+
id: { equals: "{{user_id}}" }
|
|
72
|
+
|
|
73
|
+
- name: "Delete user"
|
|
74
|
+
DELETE: /users/{{user_id}}
|
|
75
|
+
expect:
|
|
76
|
+
status: 204
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Формат шагов
|
|
80
|
+
|
|
81
|
+
HTTP-метод указывается как ключ: `GET: /path`, `POST: /path`, `PUT:`, `PATCH:`, `DELETE:`.
|
|
82
|
+
|
|
83
|
+
| Поле | Тип | Описание |
|
|
84
|
+
|------|-----|----------|
|
|
85
|
+
| `name` | string | Название шага (обязательное) |
|
|
86
|
+
| `GET/POST/PUT/PATCH/DELETE` | string | HTTP-метод + путь (обязательное) |
|
|
87
|
+
| `headers` | Record | Заголовки запроса |
|
|
88
|
+
| `json` | any | JSON-тело (auto Content-Type: application/json) |
|
|
89
|
+
| `form` | Record | Form-urlencoded тело |
|
|
90
|
+
| `query` | Record | Query-параметры |
|
|
91
|
+
| `expect` | object | Блок assertions |
|
|
92
|
+
|
|
93
|
+
### Assertions (блок expect)
|
|
94
|
+
|
|
95
|
+
| Поле | Описание |
|
|
96
|
+
|------|----------|
|
|
97
|
+
| `status` | Ожидаемый HTTP-код (exact match) |
|
|
98
|
+
| `duration` | Максимальное время ответа в мс |
|
|
99
|
+
| `headers` | Проверка заголовков ответа (exact match) |
|
|
100
|
+
| `body` | Проверка полей JSON-ответа по dot-path |
|
|
101
|
+
|
|
102
|
+
### Assertion rules (правила для body-полей)
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
body:
|
|
106
|
+
id: { type: integer } # проверка типа
|
|
107
|
+
name: { equals: "John" } # точное совпадение
|
|
108
|
+
email: { matches: ".+@.+" } # regex
|
|
109
|
+
bio: { contains: "developer" } # подстрока
|
|
110
|
+
age: { gt: 18, lt: 100 } # числовые сравнения
|
|
111
|
+
avatar: { exists: true } # поле существует
|
|
112
|
+
id: { capture: user_id } # сохранить в переменную
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Поддерживаемые типы: `string`, `integer`, `number`, `boolean`, `array`, `object`.
|
|
116
|
+
|
|
117
|
+
Вложенные поля через dot-path: `data.user.name`, `items.0.id`.
|
|
118
|
+
|
|
119
|
+
### Переменные
|
|
120
|
+
|
|
121
|
+
Синтаксис: `{{variable_name}}`
|
|
122
|
+
|
|
123
|
+
Источники значений (приоритет):
|
|
124
|
+
1. CLI-флаги (`--auth-token` → `auth_token`)
|
|
125
|
+
2. Environment (из `.env.yaml` или программно)
|
|
126
|
+
3. Captures из предыдущих шагов
|
|
127
|
+
4. Встроенные генераторы (с префиксом `$`)
|
|
128
|
+
|
|
129
|
+
### Встроенные генераторы
|
|
130
|
+
|
|
131
|
+
| Генератор | Пример | Тип |
|
|
132
|
+
|-----------|--------|-----|
|
|
133
|
+
| `{{$uuid}}` | `550e8400-e29b-41d4-a716-446655440000` | string |
|
|
134
|
+
| `{{$timestamp}}` | `1708876800` | number |
|
|
135
|
+
| `{{$randomName}}` | `John Smith` | string |
|
|
136
|
+
| `{{$randomEmail}}` | `xk92m@test.com` | string |
|
|
137
|
+
| `{{$randomInt}}` | `4217` | number |
|
|
138
|
+
| `{{$randomString}}` | `aBcDeFgH` | string |
|
|
139
|
+
|
|
140
|
+
### Config
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
config:
|
|
144
|
+
timeout: 30000 # мс, таймаут запроса (default: 30000)
|
|
145
|
+
retries: 0 # повторы при сетевой ошибке (default: 0)
|
|
146
|
+
retry_delay: 1000 # задержка между повторами (default: 1000)
|
|
147
|
+
follow_redirects: true
|
|
148
|
+
verify_ssl: true
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Retry срабатывает только на сетевые ошибки (fetch throws). HTTP 4xx/5xx — валидные ответы для assertions.
|
|
152
|
+
|
|
153
|
+
## Архитектура
|
|
154
|
+
|
|
155
|
+
### Parser (src/core/parser/)
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
parseFile("test.yaml") → Bun.file() → Bun.YAML.parse() → Zod validate → TestSuite
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
- `types.ts` — интерфейсы TypeScript
|
|
162
|
+
- `schema.ts` — Zod-схемы, method-as-key transform (`POST: /path` → `{method, path}`)
|
|
163
|
+
- `variables.ts` — подстановка `{{var}}`, генераторы, загрузка `.env.yaml`
|
|
164
|
+
- `yaml-parser.ts` — чтение файлов/директорий
|
|
165
|
+
|
|
166
|
+
### Runner (src/core/runner/)
|
|
167
|
+
|
|
168
|
+
```
|
|
169
|
+
runSuite(suite, env) → для каждого step: substitute → fetch → captures → assertions → StepResult
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- `http-client.ts` — fetch-обёртка с timeout (AbortController) и retry
|
|
173
|
+
- `assertions.ts` — проверка всех assertion rules + извлечение captures
|
|
174
|
+
- `executor.ts` — оркестратор: sequential steps, capture propagation, skip logic
|
|
175
|
+
|
|
176
|
+
### Логика выполнения
|
|
177
|
+
|
|
178
|
+
1. Для каждого шага проверяется, не зависит ли он от failed capture → skip
|
|
179
|
+
2. Подстановка переменных (env + captures) в path, headers, body, query
|
|
180
|
+
3. HTTP-запрос через fetch с timeout/retry
|
|
181
|
+
4. Извлечение captures из ответа
|
|
182
|
+
5. Проверка assertions
|
|
183
|
+
6. Если step failed/error — его captures помечаются как failed
|
|
184
|
+
|
|
185
|
+
Suites выполняются параллельно (`Promise.all`), steps внутри suite — последовательно (из-за captures).
|
|
186
|
+
|
|
187
|
+
## Environment файлы
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
# .env.yaml (по умолчанию)
|
|
191
|
+
base: http://localhost:3000/api
|
|
192
|
+
token: dev-token-123
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Загрузка:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { loadEnvironment } from "./src/core/parser/index.ts";
|
|
199
|
+
|
|
200
|
+
const env = await loadEnvironment(); // .env.yaml
|
|
201
|
+
const env = await loadEnvironment("staging"); // .env.staging.yaml
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Зависимости
|
|
205
|
+
|
|
206
|
+
- **zod** — валидация YAML-схемы
|
|
207
|
+
- Всё остальное — Bun built-in: `Bun.YAML`, `Bun.Glob`, `Bun.file()`, `Bun.sleep()`, native `fetch`
|
|
208
|
+
|
|
209
|
+
## Тесты
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
bun test # все тесты (100 tests)
|
|
213
|
+
bun test tests/parser/ # только парсер (43 tests)
|
|
214
|
+
bun test tests/runner/ # только раннер (55 tests)
|
|
215
|
+
bun test tests/integration/ # интеграционные (2 tests, real HTTP)
|
|
216
|
+
```
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
> **Исторический snapshot** на момент реализации M4+M7. Актуальная документация — [APITOOL.md](../../APITOOL.md)
|
|
2
|
+
|
|
3
|
+
# M4: Reporter + M7: CLI (базовый)
|
|
4
|
+
|
|
5
|
+
Модули вывода результатов и командной строки.
|
|
6
|
+
|
|
7
|
+
## Быстрый старт
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Запуск тестов
|
|
11
|
+
bun src/cli/index.ts run examples/jsonplaceholder.yaml
|
|
12
|
+
|
|
13
|
+
# Валидация YAML без запуска
|
|
14
|
+
bun src/cli/index.ts validate examples/jsonplaceholder.yaml
|
|
15
|
+
|
|
16
|
+
# JSON-вывод
|
|
17
|
+
bun src/cli/index.ts run tests/ --report json
|
|
18
|
+
|
|
19
|
+
# Помощь
|
|
20
|
+
bun src/cli/index.ts --help
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## CLI-команды
|
|
24
|
+
|
|
25
|
+
### `run <path>`
|
|
26
|
+
|
|
27
|
+
Запуск API-тестов. Принимает файл `.yaml` или директорию.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bun src/cli/index.ts run tests/api.yaml
|
|
31
|
+
bun src/cli/index.ts run tests/ # все YAML в директории
|
|
32
|
+
bun src/cli/index.ts run tests/ --env staging --report json --timeout 5000 --bail
|
|
33
|
+
|
|
34
|
+
# Auth-токен из внешнего источника (Keycloak, CI/CD)
|
|
35
|
+
TOKEN=$(curl -s -X POST https://keycloak/token -d 'grant_type=...' | jq -r .access_token)
|
|
36
|
+
bun src/cli/index.ts run tests/ --auth-token "$TOKEN"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Флаг | Описание | По умолчанию |
|
|
40
|
+
|------|----------|-------------|
|
|
41
|
+
| `--env <name>` | Файл окружения `.env.<name>.yaml` | `.env.yaml` |
|
|
42
|
+
| `--report <format>` | Формат вывода: `console`, `json`, `junit` | `console` |
|
|
43
|
+
| `--timeout <ms>` | Таймаут запроса (мс) | `30000` |
|
|
44
|
+
| `--bail` | Остановиться после первого упавшего suite | `false` |
|
|
45
|
+
| `--auth-token <token>` | Auth-токен, доступен как `{{auth_token}}` | — |
|
|
46
|
+
|
|
47
|
+
Exit codes:
|
|
48
|
+
- `0` — все тесты прошли
|
|
49
|
+
- `1` — есть упавшие тесты
|
|
50
|
+
- `2` — ошибка конфигурации (невалидный YAML, неверные аргументы)
|
|
51
|
+
|
|
52
|
+
### `validate <path>`
|
|
53
|
+
|
|
54
|
+
Проверка YAML-тестов без HTTP-запросов.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
bun src/cli/index.ts validate tests/api.yaml
|
|
58
|
+
# OK: 1 suite(s), 4 test(s) validated successfully
|
|
59
|
+
|
|
60
|
+
bun src/cli/index.ts validate tests/broken.yaml
|
|
61
|
+
# Error: Validation error in tests/broken.yaml: ...
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Exit codes: `0` — валидно, `2` — ошибка.
|
|
65
|
+
|
|
66
|
+
## Reporter
|
|
67
|
+
|
|
68
|
+
### Console Reporter
|
|
69
|
+
|
|
70
|
+
Цветной вывод в терминал (ANSI). Цвета отключаются автоматически при перенаправлении в файл.
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Users CRUD
|
|
74
|
+
✓ Create user (450ms)
|
|
75
|
+
✓ Get user (120ms)
|
|
76
|
+
✗ Update user (310ms)
|
|
77
|
+
status: expected equals 200 but got 500
|
|
78
|
+
○ Verify deleted (skipped)
|
|
79
|
+
|
|
80
|
+
Results: 2 passed, 1 failed, 1 skipped (1.2s)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Для нескольких suites выводится итого:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Total: 5 passed, 1 failed (2.3s)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### JSON Reporter
|
|
90
|
+
|
|
91
|
+
Сериализация `TestRunResult[]` в stdout. Для записи в файл:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
bun src/cli/index.ts run tests/ --report json > results.json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Программное использование
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { getReporter } from "./src/core/reporter/index.ts";
|
|
101
|
+
import { parseFile } from "./src/core/parser/index.ts";
|
|
102
|
+
import { runSuite } from "./src/core/runner/index.ts";
|
|
103
|
+
|
|
104
|
+
const suite = await parseFile("tests/api.yaml");
|
|
105
|
+
const result = await runSuite(suite);
|
|
106
|
+
|
|
107
|
+
// Console-вывод
|
|
108
|
+
const reporter = getReporter("console");
|
|
109
|
+
reporter.report([result]);
|
|
110
|
+
|
|
111
|
+
// JSON-вывод
|
|
112
|
+
const jsonReporter = getReporter("json");
|
|
113
|
+
jsonReporter.report([result]);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Форматирующие функции (экспортируются для кастомизации)
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import {
|
|
120
|
+
formatDuration, // (ms: number) => "450ms" | "1.2s" | "2m 5s"
|
|
121
|
+
formatStep, // (step: StepResult, color: boolean) => string
|
|
122
|
+
formatFailures, // (step: StepResult, color: boolean) => string
|
|
123
|
+
formatSuiteResult, // (result: TestRunResult, color: boolean) => string
|
|
124
|
+
formatGrandTotal, // (results: TestRunResult[], color: boolean) => string
|
|
125
|
+
} from "./src/core/reporter/index.ts";
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Архитектура
|
|
129
|
+
|
|
130
|
+
### Reporter (src/core/reporter/)
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
TestRunResult[] → getReporter("console" | "json") → report(results) → stdout
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- `types.ts` — интерфейсы Reporter, ReporterOptions, ReporterName
|
|
137
|
+
- `console.ts` — ANSI-форматирование, `✓`/`✗`/`○`, duration, assertion details
|
|
138
|
+
- `json.ts` — `JSON.stringify(results, null, 2)`
|
|
139
|
+
- `index.ts` — barrel export + `getReporter()` factory
|
|
140
|
+
|
|
141
|
+
### CLI (src/cli/)
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
process.argv → parseArgs() → command routing → run/validate → process.exitCode
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
- `index.ts` — entry point, парсинг argv, роутинг команд
|
|
148
|
+
- `output.ts` — ANSI-утилиты: `printError`, `printSuccess`, `printWarning`
|
|
149
|
+
- `commands/run.ts` — pipeline: `parse() → loadEnvironment() → runSuites() → report()`
|
|
150
|
+
- `commands/validate.ts` — `parse()` → OK / error
|
|
151
|
+
|
|
152
|
+
### Pipeline команды `run`
|
|
153
|
+
|
|
154
|
+
1. `parse(path)` — файл или директория → `TestSuite[]`
|
|
155
|
+
2. `loadEnvironment(env, dir)` — загрузка `.env.yaml`
|
|
156
|
+
3. `--auth-token` → инъекция `auth_token` в env (перезаписывает значение из файла)
|
|
157
|
+
4. `--timeout` override → мутация `suite.config.timeout`
|
|
158
|
+
5. `runSuites()` или sequential с `--bail`
|
|
159
|
+
6. `reporter.report(results)`
|
|
160
|
+
7. Exit code по результатам
|
|
161
|
+
|
|
162
|
+
### Bail mode
|
|
163
|
+
|
|
164
|
+
При `--bail` suites запускаются последовательно. Если suite содержит `failed > 0` или `error`, последующие suites пропускаются.
|
|
165
|
+
|
|
166
|
+
## Зависимости
|
|
167
|
+
|
|
168
|
+
Новых зависимостей нет. Используются:
|
|
169
|
+
- Bun built-in: `process.argv`, `process.exitCode`, `console.log`
|
|
170
|
+
- Node compat: `path.dirname`
|
|
171
|
+
- Существующие модули: Parser, Runner
|
|
172
|
+
|
|
173
|
+
## Тесты
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
bun test tests/reporter/ # reporter (25 tests)
|
|
177
|
+
bun test tests/cli/ # CLI (18 tests)
|
|
178
|
+
bun test # все unit-тесты
|
|
179
|
+
```
|