@aimeloic/monkey-tester 1.0.9 → 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/htmlTemplate.js +23 -14
- package/index.js +23 -2
- package/package.json +1 -1
package/htmlTemplate.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export function getHtmlTemplate(endpoints) {
|
|
2
|
-
// Safe stringification for HTML attribute encoding to prevent script engine parsing breaks
|
|
3
2
|
const safeJsonString = Buffer.from(JSON.stringify(endpoints)).toString('base64');
|
|
4
3
|
|
|
5
4
|
return `
|
|
@@ -65,7 +64,8 @@ export function getHtmlTemplate(endpoints) {
|
|
|
65
64
|
.field-label { font-family: 'DM Mono', monospace; font-size: 11px; color: var(--text-dim); text-align: right; }
|
|
66
65
|
input[type=text], input[type=number], select { background: var(--surface2); border: 1px solid var(--border); color: var(--text); font-family: 'DM Mono', monospace; font-size: 12px; padding: 7px 10px; border-radius: var(--radius); width: 100%; outline: none; }
|
|
67
66
|
.btn { background: var(--accent); color: #0e0c09; border: none; padding: 10px 22px; border-radius: var(--radius); font-size: 13px; font-weight: 500; cursor: pointer; }
|
|
68
|
-
.btn-
|
|
67
|
+
.btn-row { margin-top: 20px; display: flex; gap: 10px; }
|
|
68
|
+
.btn-secondary { background: var(--surface2); color: var(--text-dim); border: 1px solid var(--border); }
|
|
69
69
|
.response-panel { border-left: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; }
|
|
70
70
|
.response-header { padding: 14px 18px; border-bottom: 1px solid var(--border); display: flex; align-items: center; background: var(--surface); }
|
|
71
71
|
.response-header-title { font-size: 11px; font-family: 'DM Mono', monospace; color: var(--text-dim); text-transform: uppercase; }
|
|
@@ -151,7 +151,7 @@ function buildSidebar() {
|
|
|
151
151
|
|
|
152
152
|
function makeInputString(type, id, placeholder, defaultValue) {
|
|
153
153
|
const pAttr = placeholder ? ' placeholder="' + placeholder + '"' : '';
|
|
154
|
-
const vAttr = defaultValue !== undefined ? ' value
|
|
154
|
+
const vAttr = defaultValue !== undefined ? ' value="' + defaultValue + '"' : '';
|
|
155
155
|
return '<input type="' + type + '" id="' + id + '"' + pAttr + vAttr + ' />';
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -161,7 +161,6 @@ function renderPanel(epKey) {
|
|
|
161
161
|
const main = document.getElementById('main-panel');
|
|
162
162
|
if (!ep) return;
|
|
163
163
|
|
|
164
|
-
// FIXED: Escaped template strings (\`) prevent string concatenation mismatch errors
|
|
165
164
|
let html = \`
|
|
166
165
|
<div class="endpoint-title">\${ep.title}</div>
|
|
167
166
|
<div class="endpoint-path">
|
|
@@ -171,6 +170,7 @@ function renderPanel(epKey) {
|
|
|
171
170
|
<div class="endpoint-desc">\${ep.desc}</div>
|
|
172
171
|
\`;
|
|
173
172
|
|
|
173
|
+
// Path Parameters
|
|
174
174
|
if (ep.params && ep.params.length) {
|
|
175
175
|
html += \`<div class="form-section"><div class="form-section-title">Path Parameters</div>\`;
|
|
176
176
|
ep.params.forEach(function(p) {
|
|
@@ -185,13 +185,14 @@ function renderPanel(epKey) {
|
|
|
185
185
|
html += \`</div>\`;
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
+
// FIXED: Renders native, individual form fields instead of a single text payload editor block
|
|
188
189
|
if (ep.fields && ep.fields.length) {
|
|
189
|
-
html += \`<div class="form-section"><div class="form-section-title">JSON Request
|
|
190
|
+
html += \`<div class="form-section"><div class="form-section-title">HTTP JSON Request Payload Parameters</div>\`;
|
|
190
191
|
ep.fields.forEach(function(f) {
|
|
191
|
-
const inputHtml = makeInputString('text', 'field-' + f.name, '', '
|
|
192
|
+
const inputHtml = makeInputString(f.type || 'text', 'field-' + f.name, f.placeholder || '', '');
|
|
192
193
|
html += \`
|
|
193
194
|
<div class="field-row">
|
|
194
|
-
<label class="field-label"
|
|
195
|
+
<label class="field-label">\--\${f.label}</label>
|
|
195
196
|
\${inputHtml}
|
|
196
197
|
</div>
|
|
197
198
|
\`;
|
|
@@ -213,6 +214,7 @@ async function sendRequest() {
|
|
|
213
214
|
const ep = ENDPOINTS[currentEp];
|
|
214
215
|
let path = ep.path;
|
|
215
216
|
|
|
217
|
+
// Compile URL path parameter tags
|
|
216
218
|
if (ep.params) {
|
|
217
219
|
for (const p of ep.params) {
|
|
218
220
|
const val = document.getElementById('param-' + p.name)?.value.trim();
|
|
@@ -228,16 +230,23 @@ async function sendRequest() {
|
|
|
228
230
|
const jwt = document.getElementById('jwt-input').value.trim();
|
|
229
231
|
if (jwt) headers['Authorization'] = 'Bearer ' + jwt;
|
|
230
232
|
|
|
233
|
+
// FIXED: Dynamically bundles inputs into a background payload object structure seamlessly
|
|
231
234
|
let body = undefined;
|
|
232
235
|
if (ep.fields && ep.fields.length && ['POST', 'PUT', 'PATCH'].includes(ep.method)) {
|
|
233
|
-
const
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
236
|
+
const payloadObject = {};
|
|
237
|
+
|
|
238
|
+
for (const f of ep.fields) {
|
|
239
|
+
const inputEl = document.getElementById('field-' + f.name);
|
|
240
|
+
if (inputEl) {
|
|
241
|
+
let value = inputEl.value.trim();
|
|
242
|
+
// Cast numerical parameters to prevent type validation parsing failures
|
|
243
|
+
if (f.type === 'number' && value !== '') {
|
|
244
|
+
value = Number(value);
|
|
245
|
+
}
|
|
246
|
+
payloadObject[f.name] = value;
|
|
247
|
+
}
|
|
240
248
|
}
|
|
249
|
+
body = JSON.stringify(payloadObject);
|
|
241
250
|
}
|
|
242
251
|
|
|
243
252
|
setResponse(null, 'loading');
|
package/index.js
CHANGED
|
@@ -29,14 +29,35 @@ export function endtesterExpress() {
|
|
|
29
29
|
placeholder: 'value'
|
|
30
30
|
})) : [];
|
|
31
31
|
|
|
32
|
+
// Context-aware field mapping for common endpoints
|
|
33
|
+
let bodyFields = [];
|
|
34
|
+
if (['POST', 'PUT', 'PATCH'].includes(httpMethod)) {
|
|
35
|
+
if (path.toLowerCase().includes('login') || path.toLowerCase().includes('auth')) {
|
|
36
|
+
bodyFields = [
|
|
37
|
+
{ name: 'email', label: 'Email Address', type: 'text', placeholder: 'user@example.com' },
|
|
38
|
+
{ name: 'password', label: 'Password', type: 'text', placeholder: '••••••••' }
|
|
39
|
+
];
|
|
40
|
+
} else if (path.toLowerCase().includes('product')) {
|
|
41
|
+
bodyFields = [
|
|
42
|
+
{ name: 'name', label: 'Product Name', type: 'text', placeholder: 'Sourdough Loaf' },
|
|
43
|
+
{ name: 'price', label: 'Unit Price', type: 'number', placeholder: '5.50' },
|
|
44
|
+
{ name: 'stock', label: 'Initial Inventory', type: 'number', placeholder: '10' }
|
|
45
|
+
];
|
|
46
|
+
} else {
|
|
47
|
+
// Fallback default structure
|
|
48
|
+
bodyFields = [
|
|
49
|
+
{ name: 'key', label: 'Property Key', type: 'text', placeholder: 'value' }
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
32
54
|
detectedEndpoints[key] = {
|
|
33
55
|
method: httpMethod,
|
|
34
56
|
path: path,
|
|
35
|
-
auth: false,
|
|
36
57
|
title: `${httpMethod} ${path}`,
|
|
37
58
|
desc: `Auto-discovered endpoint: ${path}`,
|
|
38
59
|
params: pathParams,
|
|
39
|
-
fields:
|
|
60
|
+
fields: bodyFields
|
|
40
61
|
};
|
|
41
62
|
});
|
|
42
63
|
} else if (layer.name === 'router' && layer.handle && layer.handle.stack) {
|