prix-r9 1.0.3 → 2.0.0
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/LICENSE +15 -0
- package/README.md +223 -233
- package/import-curl.js +5 -4
- package/index.js +721 -371
- package/package.json +12 -7
- package/promptInforme.txt +110 -93
package/LICENSE
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) QA Team
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,233 +1,223 @@
|
|
|
1
|
-
# Prix-R9
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
prix-r9-curl -i
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
```json
|
|
142
|
-
{
|
|
143
|
-
"
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
# Convertir cURL a config JSON
|
|
226
|
-
prix-r9-curl -i mi-curl.txt -o casos/endpoint.json
|
|
227
|
-
|
|
228
|
-
# Ejecutar prueba de estrés
|
|
229
|
-
prix-r9 --config casos/endpoint.json
|
|
230
|
-
|
|
231
|
-
# Ver versión
|
|
232
|
-
prix-r9 --version
|
|
233
|
-
```
|
|
1
|
+
# Prix-R9
|
|
2
|
+
|
|
3
|
+
CLI para pruebas de carga HTTP/REST con ramp-up, multipart y escenarios encadenados por steps.
|
|
4
|
+
|
|
5
|
+
## Caracteristicas
|
|
6
|
+
|
|
7
|
+
- Ejecuta pruebas de carga con `rate` fijo o `startRate -> targetRate`.
|
|
8
|
+
- Soporta requests JSON y multipart con archivo.
|
|
9
|
+
- Permite escenarios encadenados dentro de una misma iteracion usando `steps`.
|
|
10
|
+
- Extrae valores del response JSON y los reutiliza en los siguientes steps.
|
|
11
|
+
- Mantiene compatibilidad con el formato legacy de un solo request.
|
|
12
|
+
- Genera `reporte.txt` con metricas generales del escenario y metricas por step.
|
|
13
|
+
|
|
14
|
+
## Instalacion
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install -g prix-r9
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Comandos
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
prix-r9 --config mi-config.json
|
|
24
|
+
prix-r9 --prompt
|
|
25
|
+
prix-r9-curl -i mi-curl.txt -o casos/mi-endpoint.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Flujo recomendado desde cURL
|
|
29
|
+
|
|
30
|
+
1. Exporta cada request funcional como `cURL` desde browser, Postman o Swagger.
|
|
31
|
+
2. Convierte cada cURL a un JSON base:
|
|
32
|
+
```bash
|
|
33
|
+
prix-r9-curl -i curl-upload.txt -o upload.json
|
|
34
|
+
prix-r9-curl -i curl-execute.txt -o execute.json
|
|
35
|
+
```
|
|
36
|
+
3. Toma esos JSON generados y unelos manualmente dentro de `steps`.
|
|
37
|
+
4. En el step 1 agrega `extract` con la ruta exacta del valor devuelto.
|
|
38
|
+
5. En el step 2 reemplaza el valor fijo por un placeholder `{{variableExtraida}}`.
|
|
39
|
+
6. Ejecuta el escenario encadenado con `prix-r9 --config escenario.json`.
|
|
40
|
+
|
|
41
|
+
El importador `prix-r9-curl` sigue generando configuraciones legacy de un solo request. Eso es intencional: sirven como bloque base para construir escenarios multi-step.
|
|
42
|
+
|
|
43
|
+
## Variables dinamicas
|
|
44
|
+
|
|
45
|
+
Se pueden usar en `url`, `headers`, `body`, `file` y `filekey`.
|
|
46
|
+
|
|
47
|
+
- `{{uuid}}`
|
|
48
|
+
- `{{timestamp}}`
|
|
49
|
+
- `{{random_number}}`
|
|
50
|
+
|
|
51
|
+
## Formato legacy de un request
|
|
52
|
+
|
|
53
|
+
Este formato sigue funcionando sin cambios:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"url": "https://api.tuempresa.com/v1/usuarios",
|
|
58
|
+
"method": "POST",
|
|
59
|
+
"startRate": 5,
|
|
60
|
+
"targetRate": 50,
|
|
61
|
+
"rampUpTime": 5,
|
|
62
|
+
"duration": 10,
|
|
63
|
+
"headers": {
|
|
64
|
+
"Authorization": "Bearer tu_token",
|
|
65
|
+
"X-Request-ID": "{{uuid}}"
|
|
66
|
+
},
|
|
67
|
+
"body": {
|
|
68
|
+
"id_unico": "{{uuid}}",
|
|
69
|
+
"correo_usuario": "prueba_{{timestamp}}@empresa.com"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Internamente se normaliza como un escenario de un solo step.
|
|
75
|
+
|
|
76
|
+
## Formato recomendado para escenarios encadenados
|
|
77
|
+
|
|
78
|
+
La forma mas simple es usar `steps` con el mismo formato que genera `prix-r9-curl`, sin obligarte a anidar `request`.
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"name": "Carga encadenada confirmacion de pago",
|
|
83
|
+
"startRate": 2,
|
|
84
|
+
"targetRate": 5,
|
|
85
|
+
"rampUpTime": 5,
|
|
86
|
+
"duration": 10,
|
|
87
|
+
"steps": [
|
|
88
|
+
{
|
|
89
|
+
"name": "uploadProcess",
|
|
90
|
+
"url": "https://qa.miapi.com/mdl03/api/blob/uploadProcess",
|
|
91
|
+
"method": "post",
|
|
92
|
+
"headers": {
|
|
93
|
+
"Accept": "application/json, text/plain, */*",
|
|
94
|
+
"Authorization": "Bearer tu_token"
|
|
95
|
+
},
|
|
96
|
+
"file": "./Plantillas/PlantillaMovimientoManual.csv",
|
|
97
|
+
"filekey": "File",
|
|
98
|
+
"body": {
|
|
99
|
+
"TypeFile": "1",
|
|
100
|
+
"ReasonProcess": "Carga MovimientoManualV2",
|
|
101
|
+
"CreatedBy": "Alek Rutherford",
|
|
102
|
+
"TypeProcessId": "2efff14a-94cf-4928-a6a9-ad210b487205"
|
|
103
|
+
},
|
|
104
|
+
"extract": {
|
|
105
|
+
"uploadFileProcessId": "$.uploadFileProcessId"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"name": "executeLoadProcess",
|
|
110
|
+
"url": "https://qa.miapi.com/mdl03/api/AZ/ExecuteLoadProcess",
|
|
111
|
+
"method": "post",
|
|
112
|
+
"headers": {
|
|
113
|
+
"Accept": "application/json, text/plain, */*",
|
|
114
|
+
"Content-Type": "application/json",
|
|
115
|
+
"apiKey": "tu_api_key"
|
|
116
|
+
},
|
|
117
|
+
"body": {
|
|
118
|
+
"UploadFileProcessId": "{{uploadFileProcessId}}",
|
|
119
|
+
"AprovalStatus": 1,
|
|
120
|
+
"ApprovedBy": "Alek Rutherford"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Tambien se acepta la forma anidada con `request`, pero la forma directa suele ser mas facil de mantener cuando vienes desde cURL.
|
|
128
|
+
|
|
129
|
+
## Reglas de ejecucion
|
|
130
|
+
|
|
131
|
+
- Cada iteracion crea su propio contexto.
|
|
132
|
+
- `variables` define valores iniciales opcionales por iteracion.
|
|
133
|
+
- `extract` guarda valores del response JSON para los steps siguientes.
|
|
134
|
+
- Si un step falla por HTTP, red o extraccion, la iteracion termina y los steps restantes quedan omitidos por cascade.
|
|
135
|
+
- En escenarios multi-step, el rate representa iteraciones por segundo.
|
|
136
|
+
|
|
137
|
+
## Extraccion de valores
|
|
138
|
+
|
|
139
|
+
`extract` acepta un mapa `nombreVariable -> ruta`.
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"extract": {
|
|
144
|
+
"uploadFileProcessId": "$.uploadFileProcessId",
|
|
145
|
+
"primerDetalle": "$.data[0].id"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Rutas soportadas:
|
|
151
|
+
|
|
152
|
+
- `$.propiedad`
|
|
153
|
+
- `$.objeto.hijo`
|
|
154
|
+
- `$.items[0].id`
|
|
155
|
+
- `$['propiedad-rara']`
|
|
156
|
+
|
|
157
|
+
Las rutas son case-sensitive. Si el response trae `uploadFileProcessId`, entonces `$.UploadFileProcessId` va a fallar.
|
|
158
|
+
|
|
159
|
+
## Multipart
|
|
160
|
+
|
|
161
|
+
Para multipart:
|
|
162
|
+
|
|
163
|
+
- define `file` con la ruta del archivo
|
|
164
|
+
- define `filekey` exactamente como lo espera el backend
|
|
165
|
+
- manda los campos extra en `body`
|
|
166
|
+
- no copies manualmente `Content-Type: multipart/form-data; boundary=...`; el CLI lo genera solo
|
|
167
|
+
|
|
168
|
+
Ejemplo:
|
|
169
|
+
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"url": "https://api/upload",
|
|
173
|
+
"method": "post",
|
|
174
|
+
"headers": {
|
|
175
|
+
"Authorization": "Bearer tu_token"
|
|
176
|
+
},
|
|
177
|
+
"file": "./foto.jpg",
|
|
178
|
+
"filekey": "File",
|
|
179
|
+
"body": {
|
|
180
|
+
"TypeFile": "1",
|
|
181
|
+
"ReasonProcess": "Carga {{timestamp}}"
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Metricas generadas
|
|
187
|
+
|
|
188
|
+
Al finalizar, el CLI imprime un resumen y guarda `reporte.txt` con:
|
|
189
|
+
|
|
190
|
+
- iteraciones totales, exitosas y fallidas
|
|
191
|
+
- requests ejecutados
|
|
192
|
+
- throughput real en `iter/s` y `req/s`
|
|
193
|
+
- latencia por iteracion
|
|
194
|
+
- latencia agregada por request
|
|
195
|
+
- metricas por step: ejecutado, exitoso, errores, omitido por cascade, latencia y codigos de estado
|
|
196
|
+
|
|
197
|
+
## Prompt de informe
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
prix-r9 --prompt
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Copia `promptInforme.txt` al directorio actual. El template ya esta orientado a analizar escenarios multi-step y distinguir entre metricas por iteracion y metricas por step.
|
|
204
|
+
|
|
205
|
+
## Publicacion en npm
|
|
206
|
+
|
|
207
|
+
Antes de publicar:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
npm run check
|
|
211
|
+
npm run pack:dry-run
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Si todo sale bien:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
npm login
|
|
218
|
+
npm publish --access public
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Version actual
|
|
222
|
+
|
|
223
|
+
`2.0.0`
|
package/import-curl.js
CHANGED
|
@@ -5,8 +5,8 @@ const { program } = require('commander');
|
|
|
5
5
|
const { toJsonString } = require('curlconverter');
|
|
6
6
|
|
|
7
7
|
program
|
|
8
|
-
.version('
|
|
9
|
-
.description('
|
|
8
|
+
.version('2.0.0')
|
|
9
|
+
.description('Importador de cURL a config JSON base para pruebas de carga')
|
|
10
10
|
.requiredOption('-i, --input <path>', 'Archivo de texto (.txt) que contiene el comando cURL crudo')
|
|
11
11
|
.requiredOption('-o, --output <path>', 'Ruta de destino para el config JSON de la prueba (ej: casos/az/nuevo-endpoint.json)')
|
|
12
12
|
.parse(process.argv);
|
|
@@ -105,11 +105,12 @@ try {
|
|
|
105
105
|
fs.writeFileSync(destPath, JSON.stringify(outputConfig, null, 2), 'utf8');
|
|
106
106
|
|
|
107
107
|
console.log(`✅ ¡Éxito!`);
|
|
108
|
-
console.log(`Tu comando cURL ha sido convertido a una
|
|
109
|
-
console.log(`Archivo generado: ${destPath}`);
|
|
108
|
+
console.log(`Tu comando cURL ha sido convertido a una configuracion base de carga.`);
|
|
109
|
+
console.log(`Archivo base generado: ${destPath}`);
|
|
110
110
|
console.log(`\nPuedes ejecutar la prueba ahora usando:`);
|
|
111
111
|
console.log(`prix-r9 --config ${outputPath}`);
|
|
112
112
|
|
|
113
113
|
} catch (err) {
|
|
114
114
|
console.error(`💥 Error al procesar el cURL:`, err.message);
|
|
115
115
|
}
|
|
116
|
+
|