viberadar 0.3.213 → 0.3.215
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/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -5
- package/dist/server/index.js.map +1 -1
- package/dist/ui/dashboard.html +153 -43
- package/package.json +1 -1
package/dist/ui/dashboard.html
CHANGED
|
@@ -1513,6 +1513,12 @@
|
|
|
1513
1513
|
.load-run-meta { color: var(--muted); font-size: 11px; margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
1514
1514
|
.load-run-kpi { color: var(--muted); font-size: 11px; white-space: nowrap; text-align: right; }
|
|
1515
1515
|
.load-config-hint { font-size: 11px; color: var(--muted); margin-top: 8px; line-height: 1.45; }
|
|
1516
|
+
.load-accounts-json {
|
|
1517
|
+
width: 100%; min-height: 74px; background: var(--bg); border: 1px solid var(--border);
|
|
1518
|
+
border-radius: 5px; color: var(--text); font-family: 'Cascadia Code', Consolas, monospace;
|
|
1519
|
+
font-size: 12px; padding: 8px 10px; resize: vertical; outline: none; line-height: 1.45;
|
|
1520
|
+
}
|
|
1521
|
+
.load-accounts-json:focus { border-color: var(--blue); }
|
|
1516
1522
|
.load-library-empty {
|
|
1517
1523
|
display: flex; flex-direction: column; align-items: center; justify-content: center;
|
|
1518
1524
|
padding: 60px 20px; text-align: center; color: var(--dim);
|
|
@@ -1786,6 +1792,8 @@ let loadVusDraft = 10;
|
|
|
1786
1792
|
let loadDurationDraft = '30s';
|
|
1787
1793
|
let loadDataDirDraft = '';
|
|
1788
1794
|
let loadResultDirDraft = '';
|
|
1795
|
+
let loadAccountsJsonDraft = '';
|
|
1796
|
+
let loadImportedEnvVarsDraft = {};
|
|
1789
1797
|
let loadView = 'library'; // 'library' | 'editor'
|
|
1790
1798
|
|
|
1791
1799
|
function toggleObsHint(id) {
|
|
@@ -7605,13 +7613,10 @@ async function checkK6() {
|
|
|
7605
7613
|
loadK6Available = d.available;
|
|
7606
7614
|
loadK6Version = d.version || '';
|
|
7607
7615
|
} catch { loadK6Available = false; }
|
|
7608
|
-
if (contextMode === 'load') {
|
|
7609
|
-
renderSidebar(); renderContent();
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
if (saved) { const el = document.getElementById('loadToken'); if (el) el.value = saved; }
|
|
7613
|
-
}
|
|
7614
|
-
}
|
|
7616
|
+
if (contextMode === 'load') {
|
|
7617
|
+
renderSidebar(); renderContent();
|
|
7618
|
+
}
|
|
7619
|
+
}
|
|
7615
7620
|
|
|
7616
7621
|
function buildDefaultScript(cfg) {
|
|
7617
7622
|
const baseUrl = cfg.baseUrl || 'http://localhost:5000';
|
|
@@ -7763,16 +7768,104 @@ function applyLoadConfigToFields(cfg) {
|
|
|
7763
7768
|
loadDurationDraft = cfg.duration || loadDurationDraft;
|
|
7764
7769
|
loadDataDirDraft = cfg.dataDir || loadDataDirDraft;
|
|
7765
7770
|
loadResultDirDraft = cfg.resultDir || loadResultDirDraft;
|
|
7771
|
+
if (cfg.accountsJson) loadAccountsJsonDraft = cfg.accountsJson;
|
|
7772
|
+
if (cfg.accounts) loadAccountsJsonDraft = typeof cfg.accounts === 'string' ? cfg.accounts : JSON.stringify(cfg.accounts, null, 2);
|
|
7766
7773
|
const baseEl = document.getElementById('loadBaseUrl');
|
|
7767
7774
|
const vusEl = document.getElementById('loadVus');
|
|
7768
7775
|
const durEl = document.getElementById('loadDuration');
|
|
7769
7776
|
const dataEl = document.getElementById('loadDataDir');
|
|
7770
7777
|
const resultEl = document.getElementById('loadResultDir');
|
|
7778
|
+
const accountsEl = document.getElementById('loadAccountsJson');
|
|
7771
7779
|
if (baseEl) baseEl.value = loadBaseUrlDraft;
|
|
7772
7780
|
if (vusEl) vusEl.value = loadVusDraft;
|
|
7773
7781
|
if (durEl) durEl.value = loadDurationDraft;
|
|
7774
7782
|
if (dataEl) dataEl.value = loadDataDirDraft;
|
|
7775
7783
|
if (resultEl) resultEl.value = loadResultDirDraft;
|
|
7784
|
+
if (accountsEl) accountsEl.value = loadAccountsJsonDraft;
|
|
7785
|
+
}
|
|
7786
|
+
|
|
7787
|
+
function normalizeAccountsJson(raw) {
|
|
7788
|
+
const text = (raw || '').trim();
|
|
7789
|
+
if (!text) return { text: '', accounts: [], error: null };
|
|
7790
|
+
try {
|
|
7791
|
+
const parsed = JSON.parse(text);
|
|
7792
|
+
const accounts = Array.isArray(parsed) ? parsed : [parsed];
|
|
7793
|
+
const normalized = accounts
|
|
7794
|
+
.map(a => ({
|
|
7795
|
+
email: String(a.email || a.login || a.username || '').trim(),
|
|
7796
|
+
password: String(a.password || '').trim(),
|
|
7797
|
+
}))
|
|
7798
|
+
.filter(a => a.email && a.password);
|
|
7799
|
+
if (!normalized.length) return { text, accounts: [], error: 'Accounts JSON должен содержать email/login и password' };
|
|
7800
|
+
return { text: JSON.stringify(normalized), accounts: normalized, error: null };
|
|
7801
|
+
} catch (e) {
|
|
7802
|
+
return { text, accounts: [], error: 'Accounts JSON невалидный: ' + e.message };
|
|
7803
|
+
}
|
|
7804
|
+
}
|
|
7805
|
+
|
|
7806
|
+
function normalizeLoadImport(raw, sourceName) {
|
|
7807
|
+
const root = raw && typeof raw === 'object' ? raw : {};
|
|
7808
|
+
const cfg = root.config && typeof root.config === 'object' ? { ...root.config, ...root } : root;
|
|
7809
|
+
const envVars = cfg.envVars && typeof cfg.envVars === 'object' && !Array.isArray(cfg.envVars) ? { ...cfg.envVars } : {};
|
|
7810
|
+
const imported = {
|
|
7811
|
+
scriptName: cfg.scriptName || cfg.name || (sourceName || '').replace(/\.json$/i, '') || '',
|
|
7812
|
+
script: cfg.script || cfg.k6Script || cfg.code || '',
|
|
7813
|
+
baseUrl: cfg.baseUrl || envVars.BASE_URL || '',
|
|
7814
|
+
vus: cfg.vus || cfg.VUs || cfg.users || '',
|
|
7815
|
+
duration: cfg.duration || cfg.testDuration || '',
|
|
7816
|
+
dataDir: cfg.dataDir || cfg.dataPath || '',
|
|
7817
|
+
resultDir: cfg.resultDir || cfg.resultsDir || '',
|
|
7818
|
+
accounts: cfg.accounts || cfg.usersJson || cfg.accountsJson || envVars.TEST_ACCOUNTS_JSON || '',
|
|
7819
|
+
envVars,
|
|
7820
|
+
};
|
|
7821
|
+
delete imported.envVars.BASE_URL;
|
|
7822
|
+
delete imported.envVars.TEST_ACCOUNTS_JSON;
|
|
7823
|
+
delete imported.envVars.TEST_EMAIL;
|
|
7824
|
+
delete imported.envVars.TEST_PASSWORD;
|
|
7825
|
+
return imported;
|
|
7826
|
+
}
|
|
7827
|
+
|
|
7828
|
+
function applyLoadImport(raw, sourceName) {
|
|
7829
|
+
const imported = normalizeLoadImport(raw, sourceName);
|
|
7830
|
+
if (imported.script) loadScriptDraft = String(imported.script);
|
|
7831
|
+
if (imported.scriptName) loadScriptNameDraft = String(imported.scriptName);
|
|
7832
|
+
if (imported.baseUrl) loadBaseUrlDraft = String(imported.baseUrl);
|
|
7833
|
+
if (imported.vus) loadVusDraft = parseInt(String(imported.vus), 10) || loadVusDraft;
|
|
7834
|
+
if (imported.duration) loadDurationDraft = String(imported.duration);
|
|
7835
|
+
if (imported.dataDir) loadDataDirDraft = String(imported.dataDir);
|
|
7836
|
+
if (imported.resultDir) loadResultDirDraft = String(imported.resultDir);
|
|
7837
|
+
if (imported.accounts) {
|
|
7838
|
+
loadAccountsJsonDraft = typeof imported.accounts === 'string'
|
|
7839
|
+
? imported.accounts
|
|
7840
|
+
: JSON.stringify(imported.accounts, null, 2);
|
|
7841
|
+
}
|
|
7842
|
+
loadImportedEnvVarsDraft = imported.envVars || {};
|
|
7843
|
+
loadView = 'editor';
|
|
7844
|
+
renderContent();
|
|
7845
|
+
}
|
|
7846
|
+
|
|
7847
|
+
function loadImportConfigClick() {
|
|
7848
|
+
const input = document.getElementById('loadConfigImportFile');
|
|
7849
|
+
if (input) {
|
|
7850
|
+
input.value = '';
|
|
7851
|
+
input.click();
|
|
7852
|
+
}
|
|
7853
|
+
}
|
|
7854
|
+
|
|
7855
|
+
function loadImportConfigFile(input) {
|
|
7856
|
+
const file = input && input.files && input.files[0];
|
|
7857
|
+
if (!file) return;
|
|
7858
|
+
const reader = new FileReader();
|
|
7859
|
+
reader.onload = () => {
|
|
7860
|
+
try {
|
|
7861
|
+
const raw = JSON.parse(String(reader.result || '{}'));
|
|
7862
|
+
applyLoadImport(raw, file.name);
|
|
7863
|
+
} catch (e) {
|
|
7864
|
+
alert('Конфиг не импортирован: ' + e.message);
|
|
7865
|
+
}
|
|
7866
|
+
};
|
|
7867
|
+
reader.onerror = () => alert('Не удалось прочитать файл конфига');
|
|
7868
|
+
reader.readAsText(file);
|
|
7776
7869
|
}
|
|
7777
7870
|
|
|
7778
7871
|
function renderLoad(c) {
|
|
@@ -7828,10 +7921,14 @@ function renderLoad(c) {
|
|
|
7828
7921
|
<div class="load-library-header">
|
|
7829
7922
|
<div>
|
|
7830
7923
|
<div style="font-size:16px;font-weight:600;color:var(--fg)">Нагрузочные тесты</div>
|
|
7831
|
-
<div style="font-size:12px;color:var(--muted);margin-top:2px">${loadK6Version ? escapeHtml(loadK6Version) : ''} · ${loadSavedScripts.length} сохранённых</div>
|
|
7832
|
-
</div>
|
|
7833
|
-
<
|
|
7834
|
-
|
|
7924
|
+
<div style="font-size:12px;color:var(--muted);margin-top:2px">${loadK6Version ? escapeHtml(loadK6Version) : ''} · ${loadSavedScripts.length} сохранённых</div>
|
|
7925
|
+
</div>
|
|
7926
|
+
<div class="load-btns" style="margin:0">
|
|
7927
|
+
<button class="load-btn" style="font-size:13px;padding:8px 14px" onclick="loadImportConfigClick()">Импорт конфига</button>
|
|
7928
|
+
<button class="load-btn load-btn-run" style="font-size:13px;padding:8px 20px" onclick="loadNewTest()">+ Новый тест</button>
|
|
7929
|
+
</div>
|
|
7930
|
+
</div>
|
|
7931
|
+
<input id="loadConfigImportFile" type="file" accept=".json,application/json" style="display:none" onchange="loadImportConfigFile(this)" />
|
|
7835
7932
|
|
|
7836
7933
|
${loadSavedScripts.length === 0
|
|
7837
7934
|
? `<div class="load-library-empty">
|
|
@@ -7880,10 +7977,12 @@ function renderLoad(c) {
|
|
|
7880
7977
|
|
|
7881
7978
|
c.innerHTML = `<div class="load-screen">
|
|
7882
7979
|
|
|
7883
|
-
<div class="load-editor-topbar">
|
|
7884
|
-
${!isRunning ? `<button class="load-back-btn" onclick="loadView='library';renderContent()">← Все тесты</button>` : ''}
|
|
7885
|
-
|
|
7886
|
-
|
|
7980
|
+
<div class="load-editor-topbar">
|
|
7981
|
+
${!isRunning ? `<button class="load-back-btn" onclick="loadView='library';renderContent()">← Все тесты</button>` : ''}
|
|
7982
|
+
${!isRunning ? `<button class="load-btn" style="font-size:12px;padding:5px 10px" onclick="loadImportConfigClick()">Импорт конфига</button>` : ''}
|
|
7983
|
+
<input id="loadConfigImportFile" type="file" accept=".json,application/json" style="display:none" onchange="loadImportConfigFile(this)" />
|
|
7984
|
+
<span style="font-size:12px;color:var(--muted);margin-left:4px">${statusBadge}</span>
|
|
7985
|
+
</div>
|
|
7887
7986
|
|
|
7888
7987
|
<div class="load-section">
|
|
7889
7988
|
<div class="load-section-title">Конфигурация ${loadK6Version ? `<span style="color:var(--dim);font-weight:400">${escapeHtml(loadK6Version)}</span>` : ''}</div>
|
|
@@ -7904,20 +8003,20 @@ function renderLoad(c) {
|
|
|
7904
8003
|
<div class="load-config-hint">Если в скрипте есть <code>options.scenarios</code>, VibeRadar не ломает stages через CLI, а передаёт значения как <code>__ENV.LOAD_VUS</code>/<code>__ENV.LOAD_DURATION</code> и совместимые <code>SMOKE_*</code>/<code>AUTH_*</code>. Если scenarios нет, будут использованы CLI <code>--vus</code>/<code>--duration</code>.</div>
|
|
7905
8004
|
<div class="load-config-row" style="margin-top:8px">
|
|
7906
8005
|
<div class="load-config-field" style="flex:1;min-width:260px">
|
|
7907
|
-
<label>Data dir / file <span style="color:var(--dim);font-weight:400">(
|
|
7908
|
-
<input id="loadDataDir" type="text" value="${escapeHtml(loadDataDirDraft)}" placeholder="
|
|
8006
|
+
<label>Data dir / file <span style="color:var(--dim);font-weight:400">(только если скрипт использует <code>open('./file')</code> или локальные imports)</span></label>
|
|
8007
|
+
<input id="loadDataDir" type="text" value="${escapeHtml(loadDataDirDraft)}" placeholder="Оставь пустым, если файлы не нужны" />
|
|
7909
8008
|
</div>
|
|
7910
8009
|
<div class="load-config-field" style="flex:1;min-width:260px">
|
|
7911
|
-
<label>Results dir <span style="color:var(--dim);font-weight:400">(
|
|
7912
|
-
<input id="loadResultDir" type="text" value="${escapeHtml(loadResultDirDraft)}" placeholder=".viberadar/load-runs
|
|
8010
|
+
<label>Results dir <span style="color:var(--dim);font-weight:400">(куда сохранить summary/log/metrics; можно пустым)</span></label>
|
|
8011
|
+
<input id="loadResultDir" type="text" value="${escapeHtml(loadResultDirDraft)}" placeholder="Пусто = .viberadar/load-runs/<runId>/results" />
|
|
7913
8012
|
</div>
|
|
7914
8013
|
</div>
|
|
7915
|
-
<div class="load-config-hint"
|
|
8014
|
+
<div class="load-config-hint">Data dir нужен только для локальных файлов: например, если в скрипте есть <code>open('./users.csv')</code>, укажи папку, где лежит <code>users.csv</code>. Results dir можно не заполнять.</div>
|
|
7916
8015
|
<div class="load-config-row" style="margin-top:8px">
|
|
7917
|
-
<div class="load-config-field" style="flex:1;min-width:300px">
|
|
7918
|
-
<label>
|
|
7919
|
-
<
|
|
7920
|
-
</div>
|
|
8016
|
+
<div class="load-config-field" style="flex:1;min-width:300px">
|
|
8017
|
+
<label>Accounts JSON <span style="color:var(--dim);font-weight:400">→ <code>__ENV.TEST_ACCOUNTS_JSON</code>, первая учётка также в <code>TEST_EMAIL/TEST_PASSWORD</code></span></label>
|
|
8018
|
+
<textarea class="load-accounts-json" id="loadAccountsJson" spellcheck="false" placeholder='[{"email":"user1@example.com","password":"pass1"},{"email":"user2@example.com","password":"pass2"}]'>${escapeHtml(loadAccountsJsonDraft)}</textarea>
|
|
8019
|
+
</div>
|
|
7921
8020
|
</div>
|
|
7922
8021
|
<div class="load-btns">
|
|
7923
8022
|
<button class="load-btn load-btn-run" id="loadRunBtn" onclick="runLoadTest()" ${isRunning ? 'disabled' : ''}>▶ Запустить</button>
|
|
@@ -7974,10 +8073,6 @@ function renderLoad(c) {
|
|
|
7974
8073
|
const logEl = document.getElementById('loadLogContent');
|
|
7975
8074
|
if (logEl) logEl.scrollTop = logEl.scrollHeight;
|
|
7976
8075
|
|
|
7977
|
-
// Restore token
|
|
7978
|
-
const savedToken = localStorage.getItem('vr_load_token');
|
|
7979
|
-
if (savedToken) { const el = document.getElementById('loadToken'); if (el) el.value = savedToken; }
|
|
7980
|
-
|
|
7981
8076
|
// Sync textarea with draft
|
|
7982
8077
|
const ta = document.getElementById('loadScriptEditor');
|
|
7983
8078
|
if (ta) { ta.addEventListener('input', () => { loadScriptDraft = ta.value; }); }
|
|
@@ -7986,11 +8081,13 @@ function renderLoad(c) {
|
|
|
7986
8081
|
const durationInput = document.getElementById('loadDuration');
|
|
7987
8082
|
const dataInput = document.getElementById('loadDataDir');
|
|
7988
8083
|
const resultInput = document.getElementById('loadResultDir');
|
|
8084
|
+
const accountsInput = document.getElementById('loadAccountsJson');
|
|
7989
8085
|
if (baseInput) baseInput.addEventListener('input', () => { loadBaseUrlDraft = baseInput.value || 'http://localhost:5000'; });
|
|
7990
8086
|
if (vusInput) vusInput.addEventListener('input', () => { loadVusDraft = parseInt(vusInput.value || '10', 10) || 10; });
|
|
7991
8087
|
if (durationInput) durationInput.addEventListener('input', () => { loadDurationDraft = durationInput.value || '30s'; });
|
|
7992
8088
|
if (dataInput) dataInput.addEventListener('input', () => { loadDataDirDraft = dataInput.value || ''; });
|
|
7993
8089
|
if (resultInput) resultInput.addEventListener('input', () => { loadResultDirDraft = resultInput.value || ''; });
|
|
8090
|
+
if (accountsInput) accountsInput.addEventListener('input', () => { loadAccountsJsonDraft = accountsInput.value || ''; });
|
|
7994
8091
|
|
|
7995
8092
|
// Draw charts if we have data
|
|
7996
8093
|
if (loadBuckets && loadBuckets.length > 0) {
|
|
@@ -7998,18 +8095,20 @@ function renderLoad(c) {
|
|
|
7998
8095
|
}
|
|
7999
8096
|
}
|
|
8000
8097
|
|
|
8001
|
-
function loadNewTest() {
|
|
8002
|
-
loadScriptDraft = '';
|
|
8003
|
-
loadScriptNameDraft = '';
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8098
|
+
function loadNewTest() {
|
|
8099
|
+
loadScriptDraft = '';
|
|
8100
|
+
loadScriptNameDraft = '';
|
|
8101
|
+
loadImportedEnvVarsDraft = {};
|
|
8102
|
+
loadView = 'editor';
|
|
8103
|
+
renderContent();
|
|
8104
|
+
}
|
|
8007
8105
|
|
|
8008
8106
|
function loadOpenScript(name) {
|
|
8009
8107
|
const s = loadSavedScripts.find(x => x.name === name);
|
|
8010
8108
|
if (!s) return;
|
|
8011
8109
|
loadScriptDraft = s.script;
|
|
8012
8110
|
loadScriptNameDraft = s.name;
|
|
8111
|
+
loadImportedEnvVarsDraft = {};
|
|
8013
8112
|
if (s.baseUrl) loadBaseUrlDraft = s.baseUrl;
|
|
8014
8113
|
if (s.vus) loadVusDraft = s.vus;
|
|
8015
8114
|
if (s.duration) loadDurationDraft = s.duration;
|
|
@@ -8045,19 +8144,27 @@ async function runLoadTest() {
|
|
|
8045
8144
|
const scriptName = (document.getElementById('loadScriptName')?.value || loadScriptNameDraft || 'Новый тест').trim();
|
|
8046
8145
|
const dataDir = (document.getElementById('loadDataDir')?.value || loadDataDirDraft || '').trim();
|
|
8047
8146
|
const resultDir = (document.getElementById('loadResultDir')?.value || loadResultDirDraft || '').trim();
|
|
8147
|
+
const accountsRaw = document.getElementById('loadAccountsJson')?.value || loadAccountsJsonDraft || '';
|
|
8148
|
+
const accountsInfo = normalizeAccountsJson(accountsRaw);
|
|
8149
|
+
if (accountsInfo.error) { alert(accountsInfo.error); return; }
|
|
8048
8150
|
loadBaseUrlDraft = baseUrl;
|
|
8049
8151
|
loadVusDraft = vus;
|
|
8050
8152
|
loadDurationDraft = duration;
|
|
8051
8153
|
loadScriptNameDraft = scriptName;
|
|
8052
8154
|
loadDataDirDraft = dataDir;
|
|
8053
8155
|
loadResultDirDraft = resultDir;
|
|
8156
|
+
loadAccountsJsonDraft = accountsRaw;
|
|
8054
8157
|
|
|
8055
8158
|
loadLogLines = [];
|
|
8056
8159
|
loadBuckets = [];
|
|
8057
8160
|
|
|
8058
|
-
try {
|
|
8059
|
-
const
|
|
8060
|
-
|
|
8161
|
+
try {
|
|
8162
|
+
const envVars = { ...(loadImportedEnvVarsDraft || {}) };
|
|
8163
|
+
if (accountsInfo.accounts.length > 0) {
|
|
8164
|
+
envVars.TEST_ACCOUNTS_JSON = accountsInfo.text;
|
|
8165
|
+
envVars.TEST_EMAIL = accountsInfo.accounts[0].email;
|
|
8166
|
+
envVars.TEST_PASSWORD = accountsInfo.accounts[0].password;
|
|
8167
|
+
}
|
|
8061
8168
|
|
|
8062
8169
|
const r = await fetch('/api/load/run', {
|
|
8063
8170
|
method: 'POST',
|
|
@@ -8146,12 +8253,13 @@ ${featureList || '(нет данных)'}
|
|
|
8146
8253
|
2. Можно использовать \`options.scenarios\`; тогда VibeRadar в Auto-режиме не будет передавать \`--vus/--duration\`, а прокинет значения UI в \`__ENV.SMOKE_VUS\` и \`__ENV.SMOKE_DURATION\`
|
|
8147
8254
|
3. \`export default function() { ... }\` с проверками \`check()\`
|
|
8148
8255
|
4. Base URL бери из \`__ENV.BASE_URL || '${baseUrl}'\`
|
|
8149
|
-
5. Если
|
|
8150
|
-
6. Если нужна
|
|
8151
|
-
7. Если
|
|
8152
|
-
8.
|
|
8153
|
-
9.
|
|
8154
|
-
10. Добавь
|
|
8256
|
+
5. Если нужны учётки — читай \`JSON.parse(__ENV.TEST_ACCOUNTS_JSON || '[]')\`, выбирай аккаунт по \`__VU\`; для старых скриптов доступна первая учётка как \`__ENV.TEST_EMAIL\`/\`__ENV.TEST_PASSWORD\`
|
|
8257
|
+
6. Если нужна авторизация токеном в конкретном проекте — используй env-переменную с понятным именем, например \`__ENV.API_TOKEN\`
|
|
8258
|
+
7. Если нужна загрузка файла — используй \`http.file()\` и \`open()\`
|
|
8259
|
+
8. Если нужны CSV/JSON/локальные helper-модули, используй относительные пути от Data dir: \`open('./users.csv')\`, \`import './lib/helper.js'\`
|
|
8260
|
+
9. Не добавляй \`handleSummary\` и не пиши результаты сам: VibeRadar сохраняет summary.json, metrics.ndjson, k6.log
|
|
8261
|
+
10. Добавь \`sleep(1)\` между запросами
|
|
8262
|
+
11. Добавь комментарий в начале: что тестируется и какой эндпоинт
|
|
8155
8263
|
|
|
8156
8264
|
**Шаг 3 — сохрани ТОЛЬКО скрипт в файл.**
|
|
8157
8265
|
Запиши итоговый JavaScript-код в файл: \`.viberadar/load-script-generated.js\`
|
|
@@ -8246,6 +8354,7 @@ async function loadOpenRun(runId) {
|
|
|
8246
8354
|
loadLogLines = d.logs || [];
|
|
8247
8355
|
loadScriptDraft = d.script || '';
|
|
8248
8356
|
loadScriptNameDraft = d.config?.scriptName || d.scriptName || '';
|
|
8357
|
+
loadImportedEnvVarsDraft = {};
|
|
8249
8358
|
if (d.config) applyLoadConfigToFields(d.config);
|
|
8250
8359
|
loadView = 'editor';
|
|
8251
8360
|
renderContent();
|
|
@@ -8289,6 +8398,7 @@ async function loadLoadScript(name) {
|
|
|
8289
8398
|
if (!s) return;
|
|
8290
8399
|
loadScriptDraft = s.script;
|
|
8291
8400
|
loadScriptNameDraft = s.name;
|
|
8401
|
+
loadImportedEnvVarsDraft = {};
|
|
8292
8402
|
if (s.baseUrl) loadBaseUrlDraft = s.baseUrl;
|
|
8293
8403
|
if (s.vus) loadVusDraft = s.vus;
|
|
8294
8404
|
if (s.duration) loadDurationDraft = s.duration;
|