automacao-core-carga-back 1.0.2

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/README.md ADDED
@@ -0,0 +1,348 @@
1
+ # automacao-core-carga-back
2
+
3
+ Core compartilhado de utilitários **k6** e **Playwright** para os repositórios de teste de carga dos módulos `erpx_*` e `erp_*`.
4
+
5
+ ---
6
+
7
+ ## Instalação
8
+
9
+ ```bash
10
+ npm install automacao-core-carga-back
11
+ ```
12
+
13
+ Para usar o lado Playwright, instale também o runner no seu repositório — ele é
14
+ peer dependency, para que exista uma única cópia do `@playwright/test` na árvore
15
+ (duas cópias quebram o registro de fixtures):
16
+
17
+ ```bash
18
+ npm install -D @playwright/test
19
+ ```
20
+
21
+ Quem só usa o lado k6 não precisa dele.
22
+
23
+ ---
24
+
25
+ ## ⚠️ Dois entry points, um por runtime
26
+
27
+ O pacote **não tem import raiz**. Você importa de `/k6` ou de `/playwright`:
28
+
29
+ ```js
30
+ import { K6AuthUtils } from 'automacao-core-carga-back/k6';
31
+ import { test } from 'automacao-core-carga-back/playwright';
32
+ ```
33
+
34
+ Isso não é preferência de estilo. O k6 roda num runtime Go (goja/sobek), não no
35
+ Node: não resolve `node_modules` e não expõe APIs do Node
36
+ ([doc oficial](https://grafana.com/docs/k6/latest/using-k6/modules/)). O Playwright
37
+ roda no Node. Um bundle único que misturasse os dois carregaria, de uma vez,
38
+ `require`s que só existem num dos lados, e o script k6 falhava ao carregar antes
39
+ da primeira linha de teste.
40
+
41
+ Com a separação, `dist/k6.*` referencia apenas `k6/*` e `dist/playwright.*`
42
+ apenas Node/Playwright/sharp. Não existe caminho de import que junte os dois.
43
+
44
+ ### O k6 continua precisando de bundler
45
+
46
+ O k6 não resolve pacotes por nome. Então, dentro de um teste k6,
47
+ `import ... from 'automacao-core-carga-back/k6'` só funciona se o seu
48
+ repositório tiver um passo de bundle (rollup/webpack) que resolva isso antes do
49
+ `k6 run`. Sem bundler, importe o artefato por caminho relativo:
50
+
51
+ ```js
52
+ import { K6AuthUtils } from './node_modules/automacao-core-carga-back/dist/k6.mjs';
53
+ ```
54
+
55
+ ---
56
+
57
+ ## ⚠️ Este core não guarda credenciais
58
+
59
+ Por decisão de projeto, **nenhuma credencial, string de conexão, identificador de tenant ou usuário de teste vive neste pacote**. Tudo isso é específico de ambiente e pertence a cada repositório de teste, que passa os valores como parâmetro.
60
+
61
+ Motivo: o pacote é publicado no npm, e qualquer valor aqui — inclusive dentro de `dist/bundled.js` — fica legível por quem instalar o pacote.
62
+
63
+ No seu repositório de teste:
64
+
65
+ ```bash
66
+ # .env (não versionado) ou secrets do CI
67
+ K6_USERNAME=...
68
+ K6_PASSWORD=...
69
+ DB_USER=...
70
+ DB_PASSWORD=...
71
+ DB_HOST=...
72
+ DB_PORT=...
73
+ DB_NAME=...
74
+ ```
75
+
76
+ ```bash
77
+ # k6 lê variáveis do sistema por padrão em `k6 run`; para `k6 cloud` ou
78
+ # `k6 archive` é preciso passar explicitamente com -e
79
+ k6 run -e DB_USER=$DB_USER -e DB_PASSWORD=$DB_PASSWORD test.js
80
+ ```
81
+
82
+ ---
83
+
84
+ ## Estrutura do pacote
85
+
86
+ ```
87
+ src/
88
+ ├── k6.js # Entry point do bundle k6
89
+ ├── playwright.js # Entry point do bundle Playwright
90
+ ├── types/
91
+ │ ├── k6.d.ts # Tipos de /k6
92
+ │ └── playwright.d.ts # Tipos de /playwright
93
+ └── lib/
94
+ ├── k6/
95
+ │ ├── k6AuthUtils.js # paramsHeader(), login()
96
+ │ ├── k6DataUtils.js # criaSubArrays(), somaValores()
97
+ │ ├── k6DbUtils.js # abreConexao(), pesquisa(), converteDado(), etc.
98
+ │ ├── k6ReportUtils.js # gerarSummary() para handleSummary
99
+ │ └── k6NotificationsUtils.js # pesquisar(), aguardarTotal()
100
+ └── playwright/
101
+ ├── comunsUtils.js # Login APM/Grafana, screenshots, combinarPrints, gerarUrl*
102
+ ├── apmUtils.js # Serviços, transactions e traces no APM Elastic
103
+ ├── grafanaUtils.js # Painéis RabbitMQ e Kubernetes no Grafana
104
+ └── pwIndex.js # Fixture: injeta page objects no contexto do test
105
+ ```
106
+
107
+ O pacote publicado contém apenas `dist/` e `src/types/` (ver campo `files` do
108
+ `package.json`). O build gera quatro artefatos:
109
+
110
+ | Arquivo | Formato | Consumido por |
111
+ |---|---|---|
112
+ | `dist/k6.mjs` | ESM | testes k6 (`import`) |
113
+ | `dist/k6.cjs` | CJS | testes k6 (`require`) |
114
+ | `dist/playwright.mjs` | ESM | specs Playwright (`import`) |
115
+ | `dist/playwright.cjs` | CJS | specs Playwright (`require`) |
116
+
117
+ As extensões explícitas tornam o formato inequívoco para o Node, e o mapa
118
+ `exports` do `package.json` roteia cada sintaxe para o arquivo certo.
119
+
120
+ ---
121
+
122
+ ## k6
123
+
124
+ ### Autenticação
125
+
126
+ ```js
127
+ import { K6AuthUtils } from 'automacao-core-carga-back/k6';
128
+ import http from 'k6/http';
129
+
130
+ // Credenciais vêm do seu repositório, nunca do core.
131
+ export async function setup() {
132
+ return await K6AuthUtils.login(JSON.stringify({
133
+ username: __ENV.K6_USERNAME,
134
+ password: __ENV.K6_PASSWORD,
135
+ }));
136
+ }
137
+
138
+ export default function (token) {
139
+ const params = K6AuthUtils.paramsHeader(token);
140
+ http.get(url, params);
141
+ }
142
+ ```
143
+
144
+ Para múltiplos VUs, monte o `SharedArray` a partir de um arquivo do **seu** repositório:
145
+
146
+ ```js
147
+ import { SharedArray } from 'k6/data';
148
+
149
+ const usuarios = new SharedArray('usuarios', () =>
150
+ JSON.parse(open('./data/usuarios.json'))
151
+ );
152
+ ```
153
+
154
+ ### Banco de dados
155
+
156
+ ```js
157
+ import { K6DbUtils } from 'automacao-core-carga-back/k6';
158
+
159
+ const CONEXAO = `postgres://${__ENV.DB_USER}:${__ENV.DB_PASSWORD}@${__ENV.DB_HOST}:${__ENV.DB_PORT}/${__ENV.DB_NAME}`;
160
+
161
+ export function setup() {
162
+ const db = K6DbUtils.abreConexao(CONEXAO);
163
+ const result = K6DbUtils.pesquisa(db, 'SELECT id FROM schema.tabela WHERE id = 1');
164
+ const valor = K6DbUtils.converteDado(result, 'id');
165
+ K6DbUtils.fechaConexao(db);
166
+ }
167
+ ```
168
+
169
+ Requer um binário k6 com a extensão `xk6-sql` e o driver Postgres.
170
+
171
+ ### Relatório (handleSummary)
172
+
173
+ ```js
174
+ import { K6ReportUtils } from 'automacao-core-carga-back/k6';
175
+
176
+ export function handleSummary(data) {
177
+ return K6ReportUtils.gerarSummary(data, { nome: 'calculaImpostos' });
178
+ // gera: k6/imagensIA/calculaImpostos/k6calculaImpostos.json
179
+ }
180
+ ```
181
+
182
+ Override do destino via `-e K6_JSON_DIR=...` e `-e K6_JSON_FILE=...`.
183
+
184
+ ### Helpers de array
185
+
186
+ ```js
187
+ import { K6DataUtils } from 'automacao-core-carga-back/k6';
188
+
189
+ const lotes = K6DataUtils.criaSubArrays(titulos, 10);
190
+ // [[t1..t10], [t11..t20], ...]
191
+
192
+ const somatorios = K6DataUtils.somaValores(lotes);
193
+ // ['123.50', '456.00', ...]
194
+ ```
195
+
196
+ ### Notificações
197
+
198
+ ```js
199
+ import { K6NotificationsUtils, K6AuthUtils } from 'automacao-core-carga-back/k6';
200
+
201
+ const params = K6AuthUtils.paramsHeader(token);
202
+
203
+ // Pesquisa simples:
204
+ const resultado = K6NotificationsUtils.pesquisar(JSON.stringify(input), params);
205
+
206
+ // Polling até N notificações:
207
+ K6NotificationsUtils.aguardarTotal(JSON.stringify(input), params, 5);
208
+ ```
209
+
210
+ ---
211
+
212
+ ## Playwright
213
+
214
+ ### Fixture (injeção dos page objects)
215
+
216
+ Importe `test` do pacote em vez do `@playwright/test` diretamente:
217
+
218
+ ```js
219
+ import { test, expect } from 'automacao-core-carga-back/playwright';
220
+
221
+ // Disponível em cada test via page.*:
222
+ // page.comunsUtils → ComunsUtils (login, screenshots, combinarPrints, gerarUrl*)
223
+ // page.grafanaUtils → GrafanaUtils (painéis rabbit e kubernetes)
224
+ // page.apmUtils → ApmUtils (serviços, transactions, traces)
225
+ ```
226
+
227
+ ### Exemplo de spec APM
228
+
229
+ ```js
230
+ import { test } from 'automacao-core-carga-back/playwright';
231
+ import { CONTASRECEBER } from './helpers/urls.js';
232
+
233
+ test.describe('jornada para extração de dados do apm contas a receber', {
234
+ tag: ['@APMCONTASRECEBER', '@CONTASRECEBER'],
235
+ }, () => {
236
+ test.beforeEach(async ({ page }) => {
237
+ // Credenciais do APM saem do seu repositório (env/secrets).
238
+ await page.comunsUtils.loginApm({
239
+ usuario: process.env.APM_USUARIO,
240
+ senha: process.env.APM_SENHA,
241
+ });
242
+ const url = page.comunsUtils.gerarUrlApmComDataAtual(CONTASRECEBER, '10:37:00', '11:11:00');
243
+ await page.apmUtils.acessaTelaApm(url);
244
+ });
245
+
246
+ test('01 - bridge', {
247
+ tag: '@BRIDGEAPMCONTASRECEBER',
248
+ }, async ({ page }) => {
249
+ const pasta = 'playwright/resources/imagens/contasReceber';
250
+
251
+ await page.comunsUtils.tirarPrintTelaInteira('apm', pasta);
252
+ await page.apmUtils.acessarDetalhesServico('bridge');
253
+ await page.comunsUtils.tirarPrintTelaInteira('bridge', pasta);
254
+ await page.apmUtils.acessarDetalhesTransactions('POST /erpx_fin/contas_receber/queries/gerarBaixasCompostasReceber');
255
+ await page.comunsUtils.tirarPrintTelaInteira('gerarBaixas', pasta);
256
+ await page.comunsUtils.combinarPrints(['bridge', 'gerarBaixas'], 'bridge-completo', pasta, true);
257
+ });
258
+ });
259
+ ```
260
+
261
+ ### Exemplo de spec Grafana
262
+
263
+ ```js
264
+ import { test } from 'automacao-core-carga-back/playwright';
265
+ import { CONTASRECEBER } from './helpers/urls.js';
266
+
267
+ test.describe('jornada para extração de dados do grafana', {
268
+ tag: ['@GRAFANACONTASRECEBER'],
269
+ }, () => {
270
+ test('01 - painel rabbit', async ({ page }) => {
271
+ await page.comunsUtils.loginGrafana({
272
+ email: process.env.GRAFANA_EMAIL,
273
+ senha: process.env.GRAFANA_SENHA,
274
+ });
275
+ const url = page.comunsUtils.gerarUrlGrafanaComDataAtual(CONTASRECEBER, '10:37:00', '11:11:00');
276
+ await page.grafanaUtils.acessaTelaGrafana(url);
277
+ await page.grafanaUtils.validarGrafanaCarregado();
278
+ await page.grafanaUtils.ordenarMensagensTotal();
279
+ await page.grafanaUtils.acessarVisaoCompleta('Total/unacked messages');
280
+ await page.comunsUtils.tirarPrintTelaInteira('rabbit', 'playwright/resources/imagens');
281
+ await page.grafanaUtils.voltarParaDashboard();
282
+ });
283
+ });
284
+ ```
285
+
286
+ ---
287
+
288
+ ## O que fica em cada repositório de módulo
289
+
290
+ | Artefato | Onde fica |
291
+ |---|---|
292
+ | Credenciais e config de ambiente (`.env`, secrets do CI) | Repo do módulo |
293
+ | Usuários de teste (`data/usuarios.json`) | Repo do módulo |
294
+ | String de conexão do banco e identificadores de tenant | Repo do módulo |
295
+ | `playwright/helpers/urls.js` — URLs APM/Grafana por cenário | Repo do módulo |
296
+ | `k6/pages/erpx_*/` — page objects de APIs de negócio | Repo do módulo |
297
+ | `k6/json/erpx_*/` — payloads de request | Repo do módulo |
298
+ | `k6/tests/` — scripts de teste | Repo do módulo |
299
+
300
+ ---
301
+
302
+ ## Como adicionar uma nova função ao core
303
+
304
+ 1. Crie ou edite o arquivo em `src/lib/k6/` ou `src/lib/playwright/`
305
+ 2. Exporte via classe estática: `export class MinhaClasse { static meuMetodo() {} }`
306
+ 3. Use `import` (o core é ESM; `require` não é usado em nenhum arquivo)
307
+ 4. Registre o export no entry point do lado correspondente: `src/k6.js` ou
308
+ `src/playwright.js`
309
+ 5. Declare o tipo em `src/types/k6.d.ts` ou `src/types/playwright.d.ts`. Essas
310
+ declarações são self-contained de propósito: não re-exporte de `src/lib/`,
311
+ que não vai no pacote publicado
312
+ 6. Documente com JSDoc (`@param`, `@returns`, `@example`)
313
+ 7. Nunca adicione credencial, host ou usuário — receba por parâmetro
314
+ 8. Execute `npm run build` e `npm run eslint` antes do MR
315
+ 9. Abra o MR usando o template em `.github/pull_request_template.md`
316
+
317
+ ### Não cruze os runtimes
318
+
319
+ Um arquivo em `src/lib/k6/` não pode importar `node:*`, `@playwright/test`,
320
+ `sharp` ou qualquer pacote npm — só `k6/*`. Um arquivo em `src/lib/playwright/`
321
+ não pode importar `k6/*`. Se precisar de lógica comum aos dois, ela tem que ser
322
+ JavaScript puro, sem import nenhum, e ficar duplicada ou num arquivo sem
323
+ dependências.
324
+
325
+ Para conferir que nada vazou depois do build:
326
+
327
+ ```bash
328
+ # nenhum dos dois comandos deve retornar resultado
329
+ grep -l "k6/" dist/playwright.*
330
+ grep -lE "@playwright/test|sharp|node:" dist/k6.*
331
+ ```
332
+
333
+ ---
334
+
335
+ ## Release
336
+
337
+ O pipeline de release é disparado manualmente via **Actions → Release → Run workflow**.
338
+
339
+ Selecione o tipo de bump:
340
+ - `patch` — bug fix ou ajuste interno
341
+ - `minor` — nova função sem quebrar compatibilidade
342
+ - `major` — breaking change
343
+
344
+ O workflow faz o bump de versão, cria a tag e publica no npm no mesmo run.
345
+
346
+ > A separação em dois entry points removeu o import raiz do pacote. Todo
347
+ > repositório consumidor precisa trocar `from 'automacao-core-carga-back'`
348
+ > por `/k6` ou `/playwright`, então essa mudança exige release **major**.