@poolzin/pool-bot 2026.3.9 → 2026.3.10
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/CHANGELOG.md +24 -0
- package/README.md +147 -69
- package/dist/.buildstamp +1 -1
- package/dist/agents/error-classifier.js +26 -77
- package/dist/agents/skills/security.js +1 -7
- package/dist/build-info.json +3 -3
- package/dist/cli/cron-cli/register.cron-dashboard.js +339 -0
- package/dist/cli/cron-cli/register.js +2 -0
- package/dist/cli/errors.js +187 -0
- package/dist/cli/program/command-registry.js +13 -0
- package/dist/cli/program/register.maintenance.js +21 -0
- package/dist/cli/program/register.subclis.js +9 -0
- package/dist/cli/swarm-cli/register.js +8 -0
- package/dist/cli/swarm-cli/register.swarm-status.js +488 -0
- package/dist/cli/telemetry-cli/register.js +10 -0
- package/dist/cli/telemetry-cli/register.telemetry-alerts.js +176 -0
- package/dist/cli/telemetry-cli/register.telemetry-metrics.js +323 -0
- package/dist/cli/telemetry-cli/register.telemetry-status.js +179 -0
- package/dist/commands/doctor-checks.js +498 -0
- package/dist/context-engine/index.js +1 -1
- package/dist/context-engine/legacy.js +1 -3
- package/dist/context-engine/summarizing.js +5 -8
- package/dist/cron/service/timer.js +18 -0
- package/dist/gateway/protocol/index.js +5 -2
- package/dist/gateway/protocol/schema/error-codes.js +1 -0
- package/dist/gateway/protocol/schema/swarm.js +80 -0
- package/dist/gateway/protocol/schema.js +1 -0
- package/dist/gateway/server-close.js +4 -0
- package/dist/gateway/server-constants.js +1 -0
- package/dist/gateway/server-cron.js +29 -0
- package/dist/gateway/server-maintenance.js +35 -2
- package/dist/gateway/server-methods/swarm.js +58 -0
- package/dist/gateway/server-methods/telemetry.js +71 -0
- package/dist/gateway/server-methods-list.js +8 -0
- package/dist/gateway/server-methods.js +9 -2
- package/dist/gateway/server.impl.js +33 -16
- package/dist/infra/abort-pattern.js +4 -4
- package/dist/infra/retry.js +3 -1
- package/dist/skills/commands.js +7 -25
- package/dist/skills/index.js +14 -17
- package/dist/skills/parser.js +12 -27
- package/dist/skills/registry.js +3 -6
- package/dist/skills/security.js +2 -8
- package/dist/swarm/service.js +247 -0
- package/dist/telemetry/alert-engine.js +258 -0
- package/dist/telemetry/cron-instrumentation.js +49 -0
- package/dist/telemetry/gateway-instrumentation.js +80 -0
- package/dist/telemetry/instrumentation.js +66 -0
- package/dist/telemetry/service.js +345 -0
- package/dist/tui/components/assistant-message.js +6 -2
- package/dist/tui/components/hyperlink-markdown.js +32 -0
- package/dist/tui/components/searchable-select-list.js +12 -1
- package/dist/tui/components/user-message.js +6 -2
- package/dist/tui/index.js +22 -6
- package/dist/tui/theme/theme-detection.js +226 -0
- package/dist/tui/tui-command-handlers.js +20 -0
- package/dist/tui/tui-formatters.js +4 -3
- package/dist/tui/utils/ctrl-c-handler.js +67 -0
- package/dist/tui/utils/osc8-hyperlinks.js +208 -0
- package/dist/tui/utils/safe-stop.js +180 -0
- package/dist/tui/utils/session-key-utils.js +81 -0
- package/dist/tui/utils/text-sanitization.js +284 -0
- package/dist/utils/lru-cache.js +116 -0
- package/dist/utils/performance.js +199 -0
- package/dist/utils/retry.js +240 -0
- package/docs/MELHORIAS_IMPLEMENTADAS.md +228 -0
- package/docs/MELHORIAS_PROFISSIONAIS.md +282 -0
- package/docs/PLANO_ACAO_TUI.md +357 -0
- package/docs/PROGRESSO_TUI.md +66 -0
- package/docs/RELATORIO_FINAL.md +217 -0
- package/docs/diagnostico-shell-completion.md +265 -0
- package/docs/features/advanced-memory.md +585 -0
- package/docs/features/discord-components-v2.md +277 -0
- package/docs/features/swarm.md +100 -0
- package/docs/features/telemetry.md +284 -0
- package/docs/integrations/INTEGRATION_PLAN.md +665 -345
- package/docs/models/provider-infrastructure.md +400 -0
- package/docs/security/exec-approvals.md +294 -0
- package/extensions/bluebubbles/package.json +1 -1
- package/extensions/copilot-proxy/package.json +1 -1
- package/extensions/diagnostics-otel/package.json +1 -1
- package/extensions/discord/package.json +1 -1
- package/extensions/feishu/package.json +1 -1
- package/extensions/google-antigravity-auth/package.json +1 -1
- package/extensions/google-gemini-cli-auth/package.json +1 -1
- package/extensions/googlechat/package.json +1 -1
- package/extensions/hexstrike-bridge/README.md +119 -0
- package/extensions/hexstrike-bridge/index.test.ts +247 -0
- package/extensions/hexstrike-bridge/index.ts +487 -0
- package/extensions/hexstrike-bridge/package.json +17 -0
- package/extensions/imessage/package.json +1 -1
- package/extensions/irc/package.json +1 -1
- package/extensions/line/package.json +1 -1
- package/extensions/llm-task/package.json +1 -1
- package/extensions/lobster/package.json +1 -1
- package/extensions/matrix/CHANGELOG.md +5 -0
- package/extensions/matrix/package.json +1 -1
- package/extensions/mattermost/package.json +1 -1
- package/extensions/mcp-server/index.ts +14 -0
- package/extensions/mcp-server/package.json +11 -0
- package/extensions/mcp-server/src/service.ts +540 -0
- package/extensions/memory-core/package.json +1 -1
- package/extensions/memory-lancedb/package.json +1 -1
- package/extensions/minimax-portal-auth/package.json +1 -1
- package/extensions/msteams/CHANGELOG.md +5 -0
- package/extensions/msteams/package.json +1 -1
- package/extensions/nextcloud-talk/package.json +1 -1
- package/extensions/nostr/CHANGELOG.md +5 -0
- package/extensions/nostr/package.json +1 -1
- package/extensions/open-prose/package.json +1 -1
- package/extensions/openai-codex-auth/package.json +1 -1
- package/extensions/signal/package.json +1 -1
- package/extensions/slack/package.json +1 -1
- package/extensions/telegram/package.json +1 -1
- package/extensions/tlon/package.json +1 -1
- package/extensions/twitch/CHANGELOG.md +5 -0
- package/extensions/twitch/package.json +1 -1
- package/extensions/voice-call/CHANGELOG.md +5 -0
- package/extensions/voice-call/package.json +1 -1
- package/extensions/whatsapp/package.json +1 -1
- package/extensions/zalo/CHANGELOG.md +5 -0
- package/extensions/zalo/package.json +1 -1
- package/extensions/zalouser/CHANGELOG.md +5 -0
- package/extensions/zalouser/package.json +1 -1
- package/package.json +8 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# HexStrike Bridge Extension
|
|
2
|
+
|
|
3
|
+
Integração do PoolBot com HexStrike AI - plataforma de segurança com 150+ scanners.
|
|
4
|
+
|
|
5
|
+
## Visão Geral
|
|
6
|
+
|
|
7
|
+
Esta extensão conecta o PoolBot ao HexStrike AI, permitindo executar scans de segurança diretamente via CLI e gateway.
|
|
8
|
+
|
|
9
|
+
## Funcionalidades
|
|
10
|
+
|
|
11
|
+
- **150+ ferramentas de segurança** disponíveis via HexStrike
|
|
12
|
+
- **Scans assíncronos** com acompanhamento de progresso
|
|
13
|
+
- **CLI integrada** - comandos `poolbot security`
|
|
14
|
+
- **Gateway RPC** - métodos para integração com outros sistemas
|
|
15
|
+
|
|
16
|
+
## Instalação
|
|
17
|
+
|
|
18
|
+
A extensão é carregada automaticamente pelo PoolBot quando presente no diretório `extensions/`.
|
|
19
|
+
|
|
20
|
+
## Configuração
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"hexstrike-bridge": {
|
|
25
|
+
"baseUrl": "http://localhost:8888",
|
|
26
|
+
"timeoutMs": 300000,
|
|
27
|
+
"maxConcurrentScans": 3
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
| Opção | Descrição | Padrão |
|
|
33
|
+
|-------|-----------|--------|
|
|
34
|
+
| `baseUrl` | URL da API HexStrike | `http://localhost:8888` |
|
|
35
|
+
| `timeoutMs` | Timeout de scans em ms | `300000` (5min) |
|
|
36
|
+
| `maxConcurrentScans` | Máximo de scans paralelos | `3` |
|
|
37
|
+
|
|
38
|
+
## Comandos CLI
|
|
39
|
+
|
|
40
|
+
### Verificar status
|
|
41
|
+
```bash
|
|
42
|
+
poolbot security status
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Listar ferramentas disponíveis
|
|
46
|
+
```bash
|
|
47
|
+
poolbot security tools
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Executar scan
|
|
51
|
+
```bash
|
|
52
|
+
# Scan rápido (assíncrono)
|
|
53
|
+
poolbot security scan nmap example.com
|
|
54
|
+
|
|
55
|
+
# Scan com espera
|
|
56
|
+
poolbot security scan nmap example.com --wait
|
|
57
|
+
|
|
58
|
+
# Scan com timeout customizado
|
|
59
|
+
poolbot security scan nmap example.com --wait --timeout 600
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Verificar status do scan
|
|
63
|
+
```bash
|
|
64
|
+
poolbot security scan-status <job-id>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Gateway RPC Methods
|
|
68
|
+
|
|
69
|
+
| Método | Descrição |
|
|
70
|
+
|--------|-----------|
|
|
71
|
+
| `security.status` | Status da conexão HexStrike |
|
|
72
|
+
| `security.tools.list` | Lista ferramentas disponíveis |
|
|
73
|
+
| `security.scan.start` | Inicia um novo scan |
|
|
74
|
+
| `security.scan.status` | Status de um scan específico |
|
|
75
|
+
| `security.scan.list` | Lista todos os scans ativos |
|
|
76
|
+
|
|
77
|
+
## Exemplos de Uso
|
|
78
|
+
|
|
79
|
+
### Scan de portas com Nmap
|
|
80
|
+
```bash
|
|
81
|
+
poolbot security scan nmap 192.168.1.1 --wait
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Scan de vulnerabilidades
|
|
85
|
+
```bash
|
|
86
|
+
poolbot security scan nikto https://example.com --wait
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Verificar todos os scans em andamento
|
|
90
|
+
```bash
|
|
91
|
+
poolbot security scan-list
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Requisitos
|
|
95
|
+
|
|
96
|
+
- HexStrike AI rodando (por padrão em `localhost:8888`)
|
|
97
|
+
- PoolBot v2026.3.9+
|
|
98
|
+
|
|
99
|
+
## Troubleshooting
|
|
100
|
+
|
|
101
|
+
### "HexStrike offline"
|
|
102
|
+
Verifique se o HexStrike está rodando:
|
|
103
|
+
```bash
|
|
104
|
+
curl http://localhost:8888/health
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Timeout em scans longos
|
|
108
|
+
Aumente o timeout na configuração:
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"hexstrike-bridge": {
|
|
112
|
+
"timeoutMs": 600000
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Licença
|
|
118
|
+
|
|
119
|
+
MIT - Parte do ecossistema PoolBot
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import type { PoolBotPluginApi } from "../../src/plugins/types.js";
|
|
3
|
+
import type { GatewayRequestHandlerOptions } from "../../src/gateway/server-methods/types.js";
|
|
4
|
+
|
|
5
|
+
// Mock fetch globally
|
|
6
|
+
const mockFetch = vi.fn();
|
|
7
|
+
global.fetch = mockFetch as unknown as typeof fetch;
|
|
8
|
+
|
|
9
|
+
// Import the plugin after mocking
|
|
10
|
+
const definition = (await import("./index.js")).default;
|
|
11
|
+
|
|
12
|
+
describe("hexstrike-bridge", () => {
|
|
13
|
+
let mockApi: PoolBotPluginApi;
|
|
14
|
+
let registeredMethods: Map<string, Function>;
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
registeredMethods = new Map();
|
|
19
|
+
|
|
20
|
+
mockApi = {
|
|
21
|
+
pluginConfig: {},
|
|
22
|
+
logger: {
|
|
23
|
+
info: vi.fn(),
|
|
24
|
+
warn: vi.fn(),
|
|
25
|
+
error: vi.fn(),
|
|
26
|
+
debug: vi.fn(),
|
|
27
|
+
},
|
|
28
|
+
registerGatewayMethod: vi.fn((name: string, handler: Function) => {
|
|
29
|
+
registeredMethods.set(name, handler);
|
|
30
|
+
}),
|
|
31
|
+
registerCli: vi.fn(),
|
|
32
|
+
} as unknown as PoolBotPluginApi;
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe("plugin registration", () => {
|
|
36
|
+
it("should register all gateway methods", async () => {
|
|
37
|
+
await definition.register!(mockApi);
|
|
38
|
+
|
|
39
|
+
expect(mockApi.registerGatewayMethod).toHaveBeenCalledTimes(5);
|
|
40
|
+
expect(registeredMethods.has("security.status")).toBe(true);
|
|
41
|
+
expect(registeredMethods.has("security.tools.list")).toBe(true);
|
|
42
|
+
expect(registeredMethods.has("security.scan.start")).toBe(true);
|
|
43
|
+
expect(registeredMethods.has("security.scan.status")).toBe(true);
|
|
44
|
+
expect(registeredMethods.has("security.scan.list")).toBe(true);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("should register CLI commands", async () => {
|
|
48
|
+
await definition.register!(mockApi);
|
|
49
|
+
expect(mockApi.registerCli).toHaveBeenCalledTimes(1);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe("security.status", () => {
|
|
54
|
+
it("should return healthy status when HexStrike is online", async () => {
|
|
55
|
+
mockFetch.mockResolvedValueOnce({
|
|
56
|
+
ok: true,
|
|
57
|
+
json: async () => ({ version: "1.0.0" }),
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
await definition.register!(mockApi);
|
|
61
|
+
const handler = registeredMethods.get("security.status")!;
|
|
62
|
+
|
|
63
|
+
const mockRespond = vi.fn();
|
|
64
|
+
await handler({ respond: mockRespond } as unknown as GatewayRequestHandlerOptions);
|
|
65
|
+
|
|
66
|
+
expect(mockRespond).toHaveBeenCalledWith(true, {
|
|
67
|
+
connected: true,
|
|
68
|
+
version: "1.0.0",
|
|
69
|
+
maxConcurrent: 3,
|
|
70
|
+
activeScans: 0,
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should return offline status when HexStrike is down", async () => {
|
|
75
|
+
mockFetch.mockRejectedValueOnce(new Error("Connection refused"));
|
|
76
|
+
|
|
77
|
+
await definition.register!(mockApi);
|
|
78
|
+
const handler = registeredMethods.get("security.status")!;
|
|
79
|
+
|
|
80
|
+
const mockRespond = vi.fn();
|
|
81
|
+
await handler({ respond: mockRespond } as unknown as GatewayRequestHandlerOptions);
|
|
82
|
+
|
|
83
|
+
expect(mockRespond).toHaveBeenCalledWith(true, {
|
|
84
|
+
connected: false,
|
|
85
|
+
version: undefined,
|
|
86
|
+
maxConcurrent: 3,
|
|
87
|
+
activeScans: 0,
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("security.tools.list", () => {
|
|
93
|
+
it("should return list of tools", async () => {
|
|
94
|
+
const mockTools = [
|
|
95
|
+
{ name: "nmap", description: "Port scanner", category: "recon", params: [] },
|
|
96
|
+
{ name: "nikto", description: "Web scanner", category: "web", params: [] },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
mockFetch.mockResolvedValueOnce({
|
|
100
|
+
ok: true,
|
|
101
|
+
json: async () => ({ tools: mockTools }),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
await definition.register!(mockApi);
|
|
105
|
+
const handler = registeredMethods.get("security.tools.list")!;
|
|
106
|
+
|
|
107
|
+
const mockRespond = vi.fn();
|
|
108
|
+
await handler({ respond: mockRespond } as unknown as GatewayRequestHandlerOptions);
|
|
109
|
+
|
|
110
|
+
expect(mockRespond).toHaveBeenCalledWith(true, { tools: mockTools });
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should handle API errors", async () => {
|
|
114
|
+
mockFetch.mockResolvedValueOnce({
|
|
115
|
+
ok: false,
|
|
116
|
+
status: 500,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
await definition.register!(mockApi);
|
|
120
|
+
const handler = registeredMethods.get("security.tools.list")!;
|
|
121
|
+
|
|
122
|
+
await expect(
|
|
123
|
+
handler({ respond: vi.fn() } as unknown as GatewayRequestHandlerOptions)
|
|
124
|
+
).rejects.toThrow("HexStrike API error: 500");
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe("security.scan.start", () => {
|
|
129
|
+
it("should start a scan and return job ID", async () => {
|
|
130
|
+
mockFetch.mockResolvedValueOnce({
|
|
131
|
+
ok: true,
|
|
132
|
+
json: async () => ({ result: "scan completed" }),
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
await definition.register!(mockApi);
|
|
136
|
+
const handler = registeredMethods.get("security.scan.start")!;
|
|
137
|
+
|
|
138
|
+
const mockRespond = vi.fn();
|
|
139
|
+
await handler({
|
|
140
|
+
params: { tool: "nmap", target: "example.com" },
|
|
141
|
+
respond: mockRespond,
|
|
142
|
+
} as unknown as GatewayRequestHandlerOptions);
|
|
143
|
+
|
|
144
|
+
expect(mockRespond).toHaveBeenCalledWith(true, {
|
|
145
|
+
jobId: expect.stringMatching(/^scan-\d+-[a-z0-9]+$/),
|
|
146
|
+
status: "completed",
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe("security.scan.status", () => {
|
|
152
|
+
it("should return job status for existing job", async () => {
|
|
153
|
+
mockFetch.mockResolvedValueOnce({
|
|
154
|
+
ok: true,
|
|
155
|
+
json: async () => ({ result: "done" }),
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
await definition.register!(mockApi);
|
|
159
|
+
const startHandler = registeredMethods.get("security.scan.start")!;
|
|
160
|
+
const statusHandler = registeredMethods.get("security.scan.status")!;
|
|
161
|
+
|
|
162
|
+
// Start a scan first
|
|
163
|
+
const mockRespond = vi.fn();
|
|
164
|
+
await startHandler({
|
|
165
|
+
params: { tool: "nmap", target: "example.com" },
|
|
166
|
+
respond: mockRespond,
|
|
167
|
+
} as unknown as GatewayRequestHandlerOptions);
|
|
168
|
+
|
|
169
|
+
const jobId = mockRespond.mock.calls[0][1].jobId;
|
|
170
|
+
|
|
171
|
+
// Check status
|
|
172
|
+
const statusRespond = vi.fn();
|
|
173
|
+
await statusHandler({
|
|
174
|
+
params: { jobId },
|
|
175
|
+
respond: statusRespond,
|
|
176
|
+
} as unknown as GatewayRequestHandlerOptions);
|
|
177
|
+
|
|
178
|
+
expect(statusRespond).toHaveBeenCalledWith(true, {
|
|
179
|
+
jobId,
|
|
180
|
+
status: "completed",
|
|
181
|
+
progress: 100,
|
|
182
|
+
result: { result: "done" },
|
|
183
|
+
error: undefined,
|
|
184
|
+
startedAt: expect.any(Date),
|
|
185
|
+
completedAt: expect.any(Date),
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("should return error for non-existent job", async () => {
|
|
190
|
+
await definition.register!(mockApi);
|
|
191
|
+
const handler = registeredMethods.get("security.scan.status")!;
|
|
192
|
+
|
|
193
|
+
const mockRespond = vi.fn();
|
|
194
|
+
await handler({
|
|
195
|
+
params: { jobId: "non-existent" },
|
|
196
|
+
respond: mockRespond,
|
|
197
|
+
} as unknown as GatewayRequestHandlerOptions);
|
|
198
|
+
|
|
199
|
+
expect(mockRespond).toHaveBeenCalledWith(
|
|
200
|
+
false,
|
|
201
|
+
undefined,
|
|
202
|
+
expect.objectContaining({
|
|
203
|
+
code: "INVALID_REQUEST",
|
|
204
|
+
message: "Job not found: non-existent",
|
|
205
|
+
})
|
|
206
|
+
);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
describe("security.scan.list", () => {
|
|
211
|
+
it("should return all jobs", async () => {
|
|
212
|
+
mockFetch.mockResolvedValueOnce({
|
|
213
|
+
ok: true,
|
|
214
|
+
json: async () => ({ result: "done" }),
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
await definition.register!(mockApi);
|
|
218
|
+
const startHandler = registeredMethods.get("security.scan.start")!;
|
|
219
|
+
const listHandler = registeredMethods.get("security.scan.list")!;
|
|
220
|
+
|
|
221
|
+
// Start a scan
|
|
222
|
+
await startHandler({
|
|
223
|
+
params: { tool: "nmap", target: "example.com" },
|
|
224
|
+
respond: vi.fn(),
|
|
225
|
+
} as unknown as GatewayRequestHandlerOptions);
|
|
226
|
+
|
|
227
|
+
// List jobs
|
|
228
|
+
const mockRespond = vi.fn();
|
|
229
|
+
await listHandler({ respond: mockRespond } as unknown as GatewayRequestHandlerOptions);
|
|
230
|
+
|
|
231
|
+
expect(mockRespond).toHaveBeenCalledWith(
|
|
232
|
+
true,
|
|
233
|
+
expect.objectContaining({
|
|
234
|
+
jobs: expect.arrayContaining([
|
|
235
|
+
expect.objectContaining({
|
|
236
|
+
jobId: expect.stringMatching(/^scan-\d+-[a-z0-9]+$/),
|
|
237
|
+
tool: "nmap",
|
|
238
|
+
target: "example.com",
|
|
239
|
+
status: "completed",
|
|
240
|
+
progress: 100,
|
|
241
|
+
}),
|
|
242
|
+
]),
|
|
243
|
+
})
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
});
|