lib-e2e-cypress-for-dummys-ts 0.1.0 → 0.3.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/README.md +87 -1
- package/dist/index.cjs +562 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -1
- package/dist/index.d.ts +19 -1
- package/dist/index.js +559 -83
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -92,7 +92,9 @@ var I18N_ES = {
|
|
|
92
92
|
NO_TAGS: "Sin etiquetas",
|
|
93
93
|
SAVE_BTN: "\u{1F4BE} Guardar",
|
|
94
94
|
SAVE_AND_EDIT: "\u{1F4DD} Guardar y editar",
|
|
95
|
-
REMOVE_TAG_TITLE: "Quitar"
|
|
95
|
+
REMOVE_TAG_TITLE: "Quitar",
|
|
96
|
+
NOTES_LABEL: "Descripci\xF3n / Notas (opcional):",
|
|
97
|
+
NOTES_PLACEHOLDER: "Qu\xE9 valida este test, condiciones previas, etc."
|
|
96
98
|
},
|
|
97
99
|
TEST_EDITOR: {
|
|
98
100
|
NO_TAGS: "Sin etiquetas",
|
|
@@ -141,7 +143,10 @@ var I18N_ES = {
|
|
|
141
143
|
JSON_BAD_FORMAT: "El archivo no tiene el formato esperado.",
|
|
142
144
|
SMART_SELECTOR_SECTION: "\u{1F50D} Selector inteligente",
|
|
143
145
|
SMART_SELECTOR_TITLE: "Selector inteligente",
|
|
144
|
-
SMART_SELECTOR_SUB: "Muestra un picker al hacer click en elementos sin selector v\xE1lido."
|
|
146
|
+
SMART_SELECTOR_SUB: "Muestra un picker al hacer click en elementos sin selector v\xE1lido.",
|
|
147
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilidad del widget",
|
|
148
|
+
START_HIDDEN_TITLE: "Iniciar oculto",
|
|
149
|
+
START_HIDDEN_SUB: "El widget arranca invisible. Usa Ctrl+Shift+E para mostrarlo u ocultarlo."
|
|
145
150
|
},
|
|
146
151
|
SELECTOR_PICKER: {
|
|
147
152
|
TITLE: "Selecciona un elemento del DOM",
|
|
@@ -180,7 +185,12 @@ var I18N_ES = {
|
|
|
180
185
|
COPY_ICP_BTN: "\u{1F4CB} Copiar interceptores",
|
|
181
186
|
INSERT_BTN: "\u{1F4BE} Insertar en archivo",
|
|
182
187
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Editar manualmente",
|
|
183
|
-
CLOSE_BTN: "\u2715 Cerrar"
|
|
188
|
+
CLOSE_BTN: "\u2715 Cerrar",
|
|
189
|
+
NEW_FILE_BTN: "+ Nuevo archivo",
|
|
190
|
+
REFRESH_BTN: "\u21BB Actualizar",
|
|
191
|
+
NEW_FILE_PLACEHOLDER: "nombre-del-test",
|
|
192
|
+
NEW_FILE_CONFIRM: "Crear",
|
|
193
|
+
NEW_FILE_CANCEL: "Cancelar"
|
|
184
194
|
},
|
|
185
195
|
FILE_PREVIEW: {
|
|
186
196
|
NO_FILE: "Sin archivo",
|
|
@@ -249,7 +259,9 @@ var I18N_EN = {
|
|
|
249
259
|
NO_TAGS: "No tags",
|
|
250
260
|
SAVE_BTN: "\u{1F4BE} Save",
|
|
251
261
|
SAVE_AND_EDIT: "\u{1F4DD} Save and edit",
|
|
252
|
-
REMOVE_TAG_TITLE: "Remove"
|
|
262
|
+
REMOVE_TAG_TITLE: "Remove",
|
|
263
|
+
NOTES_LABEL: "Description / Notes (optional):",
|
|
264
|
+
NOTES_PLACEHOLDER: "What this test validates, preconditions, etc."
|
|
253
265
|
},
|
|
254
266
|
TEST_EDITOR: {
|
|
255
267
|
NO_TAGS: "No tags",
|
|
@@ -298,7 +310,10 @@ var I18N_EN = {
|
|
|
298
310
|
JSON_BAD_FORMAT: "The file does not have the expected format.",
|
|
299
311
|
SMART_SELECTOR_SECTION: "\u{1F50D} Smart selector",
|
|
300
312
|
SMART_SELECTOR_TITLE: "Smart selector",
|
|
301
|
-
SMART_SELECTOR_SUB: "Shows a picker when clicking elements with no valid selector."
|
|
313
|
+
SMART_SELECTOR_SUB: "Shows a picker when clicking elements with no valid selector.",
|
|
314
|
+
START_HIDDEN_SECTION: "\u{1F441} Widget visibility",
|
|
315
|
+
START_HIDDEN_TITLE: "Start hidden",
|
|
316
|
+
START_HIDDEN_SUB: "The widget starts invisible. Use Ctrl+Shift+E to show or hide it."
|
|
302
317
|
},
|
|
303
318
|
SELECTOR_PICKER: {
|
|
304
319
|
TITLE: "Select a DOM element",
|
|
@@ -337,7 +352,12 @@ var I18N_EN = {
|
|
|
337
352
|
COPY_ICP_BTN: "\u{1F4CB} Copy interceptors",
|
|
338
353
|
INSERT_BTN: "\u{1F4BE} Insert into file",
|
|
339
354
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Edit manually",
|
|
340
|
-
CLOSE_BTN: "\u2715 Close"
|
|
355
|
+
CLOSE_BTN: "\u2715 Close",
|
|
356
|
+
NEW_FILE_BTN: "+ New file",
|
|
357
|
+
REFRESH_BTN: "\u21BB Refresh",
|
|
358
|
+
NEW_FILE_PLACEHOLDER: "test-name",
|
|
359
|
+
NEW_FILE_CONFIRM: "Create",
|
|
360
|
+
NEW_FILE_CANCEL: "Cancel"
|
|
341
361
|
},
|
|
342
362
|
FILE_PREVIEW: {
|
|
343
363
|
NO_FILE: "No file",
|
|
@@ -406,7 +426,9 @@ var I18N_FR = {
|
|
|
406
426
|
NO_TAGS: "Sans \xE9tiquettes",
|
|
407
427
|
SAVE_BTN: "\u{1F4BE} Enregistrer",
|
|
408
428
|
SAVE_AND_EDIT: "\u{1F4DD} Enregistrer et \xE9diter",
|
|
409
|
-
REMOVE_TAG_TITLE: "Retirer"
|
|
429
|
+
REMOVE_TAG_TITLE: "Retirer",
|
|
430
|
+
NOTES_LABEL: "Description / Notes (optionnel) :",
|
|
431
|
+
NOTES_PLACEHOLDER: "Ce que ce test valide, conditions pr\xE9alables, etc."
|
|
410
432
|
},
|
|
411
433
|
TEST_EDITOR: {
|
|
412
434
|
NO_TAGS: "Sans \xE9tiquettes",
|
|
@@ -455,7 +477,10 @@ var I18N_FR = {
|
|
|
455
477
|
JSON_BAD_FORMAT: "Le fichier n'a pas le format attendu.",
|
|
456
478
|
SMART_SELECTOR_SECTION: "\u{1F50D} S\xE9lecteur intelligent",
|
|
457
479
|
SMART_SELECTOR_TITLE: "S\xE9lecteur intelligent",
|
|
458
|
-
SMART_SELECTOR_SUB: "Affiche un s\xE9lecteur lors du clic sur des \xE9l\xE9ments sans s\xE9lecteur valide."
|
|
480
|
+
SMART_SELECTOR_SUB: "Affiche un s\xE9lecteur lors du clic sur des \xE9l\xE9ments sans s\xE9lecteur valide.",
|
|
481
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilit\xE9 du widget",
|
|
482
|
+
START_HIDDEN_TITLE: "D\xE9marrer masqu\xE9",
|
|
483
|
+
START_HIDDEN_SUB: "Le widget d\xE9marre invisible. Utilisez Ctrl+Shift+E pour l'afficher ou le masquer."
|
|
459
484
|
},
|
|
460
485
|
SELECTOR_PICKER: {
|
|
461
486
|
TITLE: "S\xE9lectionnez un \xE9l\xE9ment du DOM",
|
|
@@ -494,7 +519,12 @@ var I18N_FR = {
|
|
|
494
519
|
COPY_ICP_BTN: "\u{1F4CB} Copier les intercepteurs",
|
|
495
520
|
INSERT_BTN: "\u{1F4BE} Ins\xE9rer dans le fichier",
|
|
496
521
|
EDIT_MANUAL_BTN: "\u270F\uFE0F \xC9diter manuellement",
|
|
497
|
-
CLOSE_BTN: "\u2715 Fermer"
|
|
522
|
+
CLOSE_BTN: "\u2715 Fermer",
|
|
523
|
+
NEW_FILE_BTN: "+ Nouveau fichier",
|
|
524
|
+
REFRESH_BTN: "\u21BB Actualiser",
|
|
525
|
+
NEW_FILE_PLACEHOLDER: "nom-du-test",
|
|
526
|
+
NEW_FILE_CONFIRM: "Cr\xE9er",
|
|
527
|
+
NEW_FILE_CANCEL: "Annuler"
|
|
498
528
|
},
|
|
499
529
|
FILE_PREVIEW: {
|
|
500
530
|
NO_FILE: "Sans fichier",
|
|
@@ -563,7 +593,9 @@ var I18N_IT = {
|
|
|
563
593
|
NO_TAGS: "Nessuna etichetta",
|
|
564
594
|
SAVE_BTN: "\u{1F4BE} Salva",
|
|
565
595
|
SAVE_AND_EDIT: "\u{1F4DD} Salva e modifica",
|
|
566
|
-
REMOVE_TAG_TITLE: "Rimuovi"
|
|
596
|
+
REMOVE_TAG_TITLE: "Rimuovi",
|
|
597
|
+
NOTES_LABEL: "Descrizione / Note (opzionale):",
|
|
598
|
+
NOTES_PLACEHOLDER: "Cosa valida questo test, condizioni preliminari, ecc."
|
|
567
599
|
},
|
|
568
600
|
TEST_EDITOR: {
|
|
569
601
|
NO_TAGS: "Nessuna etichetta",
|
|
@@ -612,7 +644,10 @@ var I18N_IT = {
|
|
|
612
644
|
JSON_BAD_FORMAT: "Il file non ha il formato previsto.",
|
|
613
645
|
SMART_SELECTOR_SECTION: "\u{1F50D} Selettore intelligente",
|
|
614
646
|
SMART_SELECTOR_TITLE: "Selettore intelligente",
|
|
615
|
-
SMART_SELECTOR_SUB: "Mostra un selettore quando si fa clic su elementi senza selettore valido."
|
|
647
|
+
SMART_SELECTOR_SUB: "Mostra un selettore quando si fa clic su elementi senza selettore valido.",
|
|
648
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilit\xE0 del widget",
|
|
649
|
+
START_HIDDEN_TITLE: "Avvia nascosto",
|
|
650
|
+
START_HIDDEN_SUB: "Il widget si avvia invisibile. Usa Ctrl+Shift+E per mostrarlo o nasconderlo."
|
|
616
651
|
},
|
|
617
652
|
SELECTOR_PICKER: {
|
|
618
653
|
TITLE: "Seleziona un elemento DOM",
|
|
@@ -651,7 +686,12 @@ var I18N_IT = {
|
|
|
651
686
|
COPY_ICP_BTN: "\u{1F4CB} Copia interceptor",
|
|
652
687
|
INSERT_BTN: "\u{1F4BE} Inserisci nel file",
|
|
653
688
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Modifica manualmente",
|
|
654
|
-
CLOSE_BTN: "\u2715 Chiudi"
|
|
689
|
+
CLOSE_BTN: "\u2715 Chiudi",
|
|
690
|
+
NEW_FILE_BTN: "+ Nuovo file",
|
|
691
|
+
REFRESH_BTN: "\u21BB Aggiorna",
|
|
692
|
+
NEW_FILE_PLACEHOLDER: "nome-del-test",
|
|
693
|
+
NEW_FILE_CONFIRM: "Crea",
|
|
694
|
+
NEW_FILE_CANCEL: "Annulla"
|
|
655
695
|
},
|
|
656
696
|
FILE_PREVIEW: {
|
|
657
697
|
NO_FILE: "Nessun file",
|
|
@@ -720,7 +760,9 @@ var I18N_DE = {
|
|
|
720
760
|
NO_TAGS: "Keine Tags",
|
|
721
761
|
SAVE_BTN: "\u{1F4BE} Speichern",
|
|
722
762
|
SAVE_AND_EDIT: "\u{1F4DD} Speichern und bearbeiten",
|
|
723
|
-
REMOVE_TAG_TITLE: "Entfernen"
|
|
763
|
+
REMOVE_TAG_TITLE: "Entfernen",
|
|
764
|
+
NOTES_LABEL: "Beschreibung / Notizen (optional):",
|
|
765
|
+
NOTES_PLACEHOLDER: "Was dieser Test validiert, Voraussetzungen usw."
|
|
724
766
|
},
|
|
725
767
|
TEST_EDITOR: {
|
|
726
768
|
NO_TAGS: "Keine Tags",
|
|
@@ -769,7 +811,10 @@ var I18N_DE = {
|
|
|
769
811
|
JSON_BAD_FORMAT: "Die Datei hat nicht das erwartete Format.",
|
|
770
812
|
SMART_SELECTOR_SECTION: "\u{1F50D} Intelligenter Selektor",
|
|
771
813
|
SMART_SELECTOR_TITLE: "Intelligenter Selektor",
|
|
772
|
-
SMART_SELECTOR_SUB: "Zeigt ein Auswahlfeld, wenn auf Elemente ohne g\xFCltigen Selektor geklickt wird."
|
|
814
|
+
SMART_SELECTOR_SUB: "Zeigt ein Auswahlfeld, wenn auf Elemente ohne g\xFCltigen Selektor geklickt wird.",
|
|
815
|
+
START_HIDDEN_SECTION: "\u{1F441} Widget-Sichtbarkeit",
|
|
816
|
+
START_HIDDEN_TITLE: "Versteckt starten",
|
|
817
|
+
START_HIDDEN_SUB: "Das Widget startet unsichtbar. Verwenden Sie Ctrl+Shift+E zum Ein-/Ausblenden."
|
|
773
818
|
},
|
|
774
819
|
SELECTOR_PICKER: {
|
|
775
820
|
TITLE: "DOM-Element ausw\xE4hlen",
|
|
@@ -808,7 +853,12 @@ var I18N_DE = {
|
|
|
808
853
|
COPY_ICP_BTN: "\u{1F4CB} Interceptors kopieren",
|
|
809
854
|
INSERT_BTN: "\u{1F4BE} In Datei einf\xFCgen",
|
|
810
855
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Manuell bearbeiten",
|
|
811
|
-
CLOSE_BTN: "\u2715 Schlie\xDFen"
|
|
856
|
+
CLOSE_BTN: "\u2715 Schlie\xDFen",
|
|
857
|
+
NEW_FILE_BTN: "+ Neue Datei",
|
|
858
|
+
REFRESH_BTN: "\u21BB Aktualisieren",
|
|
859
|
+
NEW_FILE_PLACEHOLDER: "test-name",
|
|
860
|
+
NEW_FILE_CONFIRM: "Erstellen",
|
|
861
|
+
NEW_FILE_CANCEL: "Abbrechen"
|
|
812
862
|
},
|
|
813
863
|
FILE_PREVIEW: {
|
|
814
864
|
NO_FILE: "Keine Datei",
|
|
@@ -890,13 +940,37 @@ var TranslationService = class {
|
|
|
890
940
|
};
|
|
891
941
|
var translationService = new TranslationService();
|
|
892
942
|
|
|
943
|
+
// src/utils/code-format.utils.ts
|
|
944
|
+
function gcd(a, b) {
|
|
945
|
+
while (b) {
|
|
946
|
+
const t = b;
|
|
947
|
+
b = a % b;
|
|
948
|
+
a = t;
|
|
949
|
+
}
|
|
950
|
+
return a;
|
|
951
|
+
}
|
|
952
|
+
function normalizeBlock(code, baseIndent) {
|
|
953
|
+
const lines = code.split("\n").map((l) => l.trimEnd());
|
|
954
|
+
const nonEmpty = lines.filter((l) => l.trim().length > 0);
|
|
955
|
+
if (!nonEmpty.length) return "";
|
|
956
|
+
const indents = nonEmpty.map((l) => l.length - l.trimStart().length);
|
|
957
|
+
const minIndent = Math.min(...indents);
|
|
958
|
+
const relIndents = [...new Set(indents.map((n) => n - minIndent).filter((n) => n > 0))];
|
|
959
|
+
const step = relIndents.length > 0 ? relIndents.reduce(gcd) : 2;
|
|
960
|
+
return lines.map((l) => {
|
|
961
|
+
if (!l.trim()) return "";
|
|
962
|
+
const level = Math.round((l.length - l.trimStart().length - minIndent) / step);
|
|
963
|
+
return baseIndent + " ".repeat(level) + l.trimStart();
|
|
964
|
+
}).join("\n");
|
|
965
|
+
}
|
|
966
|
+
|
|
893
967
|
// src/services/transformation.service.ts
|
|
894
968
|
var TransformationService = class {
|
|
895
969
|
toLang(lang) {
|
|
896
970
|
return isLang(lang) ? lang : "en";
|
|
897
971
|
}
|
|
898
972
|
generateItDescription(description, commands) {
|
|
899
|
-
const commandsBlock = commands.map((cmd) =>
|
|
973
|
+
const commandsBlock = commands.map((cmd) => normalizeBlock(cmd, " ")).join("\n");
|
|
900
974
|
return `it('${description}', () => {
|
|
901
975
|
${commandsBlock}
|
|
902
976
|
});`;
|
|
@@ -927,6 +1001,13 @@ ${interceptors} })
|
|
|
927
1001
|
}
|
|
928
1002
|
return content.slice(0, idx) + "\n" + itBlock + "\n" + content.slice(idx);
|
|
929
1003
|
}
|
|
1004
|
+
buildBlockComment(notes) {
|
|
1005
|
+
if (!notes.trim()) return "";
|
|
1006
|
+
const lines = notes.split("\n").map((l) => ` * ${l}`).join("\n");
|
|
1007
|
+
return `/**
|
|
1008
|
+
${lines}
|
|
1009
|
+
*/`;
|
|
1010
|
+
}
|
|
930
1011
|
isFile(file) {
|
|
931
1012
|
return !!file && file.kind === "file";
|
|
932
1013
|
}
|
|
@@ -1337,9 +1418,9 @@ var PersistenceService = class {
|
|
|
1337
1418
|
return this._db;
|
|
1338
1419
|
}
|
|
1339
1420
|
// ── Tests ─────────────────────────────────────────────────────────────────
|
|
1340
|
-
async insertTest(name, commands = [], interceptors = [], tags = []) {
|
|
1421
|
+
async insertTest(name, commands = [], interceptors = [], tags = [], notes) {
|
|
1341
1422
|
const db = await this.getDB();
|
|
1342
|
-
const record = { name, createdAt: Date.now(), ...tags.length ? { tags } : {} };
|
|
1423
|
+
const record = { name, createdAt: Date.now(), ...tags.length ? { tags } : {}, ...notes ? { notes } : {} };
|
|
1343
1424
|
const id = await db.add("tests", record);
|
|
1344
1425
|
if (commands.length) await this.insertCommands(commands, id);
|
|
1345
1426
|
if (interceptors.length) await this.insertInterceptors(interceptors, id);
|
|
@@ -1363,9 +1444,9 @@ var PersistenceService = class {
|
|
|
1363
1444
|
const commands = await this.getCommandStrings(testId);
|
|
1364
1445
|
const interceptors = await this.getInterceptorStrings(testId);
|
|
1365
1446
|
const itBlock = `it('${record.name}', () => {
|
|
1366
|
-
|
|
1447
|
+
${commands.map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
1367
1448
|
});`;
|
|
1368
|
-
const interceptorsBlock = interceptors.length ? " // Auto-generated Cypress interceptors\n" + interceptors.map((i) => " "
|
|
1449
|
+
const interceptorsBlock = interceptors.length ? " // Auto-generated Cypress interceptors\n" + interceptors.map((i) => normalizeBlock(i, " ")).join("\n") + "\n" : "";
|
|
1369
1450
|
return { ...record, commands, interceptors, cypressCommands: commands, itBlock, interceptorsBlock };
|
|
1370
1451
|
}
|
|
1371
1452
|
async deleteTest(id) {
|
|
@@ -2104,7 +2185,8 @@ if (!customElements.get("test-previsualizer")) {
|
|
|
2104
2185
|
var SAVE_TEST_STYLES = `
|
|
2105
2186
|
:host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }
|
|
2106
2187
|
* { box-sizing: border-box; }
|
|
2107
|
-
.container { padding: 24px 28px; text-align:
|
|
2188
|
+
.container { padding: 24px 28px; text-align: left; }
|
|
2189
|
+
.btn-row, p { text-align: center; }
|
|
2108
2190
|
p { margin: 0 0 20px; font-size: 14px; color: #8b949e; line-height: 1.5; }
|
|
2109
2191
|
.btn-row { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }
|
|
2110
2192
|
button {
|
|
@@ -2126,6 +2208,15 @@ var SAVE_TEST_STYLES = `
|
|
|
2126
2208
|
}
|
|
2127
2209
|
input[type="text"]:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }
|
|
2128
2210
|
input[type="text"]::placeholder { color: #484f58; }
|
|
2211
|
+
textarea {
|
|
2212
|
+
width: 100%; padding: 10px 14px; border: 1px solid #30363d;
|
|
2213
|
+
border-radius: 8px; background: #0d1117; color: #e6edf3;
|
|
2214
|
+
font-size: 14px; outline: none; margin-bottom: 4px;
|
|
2215
|
+
font-family: inherit; resize: vertical; line-height: 1.5;
|
|
2216
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
2217
|
+
}
|
|
2218
|
+
textarea:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }
|
|
2219
|
+
textarea::placeholder { color: #484f58; }
|
|
2129
2220
|
.tag-label {
|
|
2130
2221
|
font-size: 11px; color: #484f58; text-align: left; margin-bottom: 5px; display: block;
|
|
2131
2222
|
}
|
|
@@ -2164,7 +2255,7 @@ function renderSaveTestAsk(t) {
|
|
|
2164
2255
|
</div>
|
|
2165
2256
|
</div>`;
|
|
2166
2257
|
}
|
|
2167
|
-
function renderSaveTestDesc(description, tags, t) {
|
|
2258
|
+
function renderSaveTestDesc(description, notes, tags, t) {
|
|
2168
2259
|
const chipsHtml = tags.map(
|
|
2169
2260
|
(tag) => `<span class="chip">${escHtml(tag)}<button class="chip-del" data-tag="${escAttr(tag)}" title="${t("SAVE_TEST.REMOVE_TAG_TITLE")}">\u2715</button></span>`
|
|
2170
2261
|
).join("");
|
|
@@ -2173,6 +2264,8 @@ function renderSaveTestDesc(description, tags, t) {
|
|
|
2173
2264
|
<p>${t("SAVE_TEST.DESC_LABEL")} (<code>it()</code>):</p>
|
|
2174
2265
|
<input id="desc-input" type="text" placeholder="${t("SAVE_TEST.DESC_PLACEHOLDER")}"
|
|
2175
2266
|
value="${escAttr(description)}" autocomplete="off" />
|
|
2267
|
+
<span class="tag-label">${t("SAVE_TEST.NOTES_LABEL")}</span>
|
|
2268
|
+
<textarea id="notes-input" rows="3" placeholder="${escAttr(t("SAVE_TEST.NOTES_PLACEHOLDER"))}">${escHtml(notes)}</textarea>
|
|
2176
2269
|
<span class="tag-label">${t("SAVE_TEST.TAGS_LABEL")}</span>
|
|
2177
2270
|
<div class="tag-input-row">
|
|
2178
2271
|
<input id="tag-input" type="text" placeholder="${t("SAVE_TEST.TAGS_PLACEHOLDER")}" autocomplete="off" />
|
|
@@ -2192,6 +2285,7 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2192
2285
|
shadow;
|
|
2193
2286
|
_step = "ask";
|
|
2194
2287
|
description = "";
|
|
2288
|
+
notes = "";
|
|
2195
2289
|
tags = [];
|
|
2196
2290
|
translation = translationService;
|
|
2197
2291
|
constructor() {
|
|
@@ -2209,17 +2303,18 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2209
2303
|
this.render();
|
|
2210
2304
|
}
|
|
2211
2305
|
confirmSave() {
|
|
2212
|
-
this.dispatch("savetest", { description: this.description.trim(), tags: [...this.tags] });
|
|
2306
|
+
this.dispatch("savetest", { description: this.description.trim(), notes: this.notes, tags: [...this.tags] });
|
|
2213
2307
|
}
|
|
2214
2308
|
confirmSaveAndExport() {
|
|
2215
|
-
this.dispatch("saveandexport", { description: this.description.trim(), tags: [...this.tags] });
|
|
2309
|
+
this.dispatch("saveandexport", { description: this.description.trim(), notes: this.notes, tags: [...this.tags] });
|
|
2216
2310
|
}
|
|
2217
2311
|
cancel() {
|
|
2218
|
-
this.dispatch("savetest", { description: null, tags: [] });
|
|
2312
|
+
this.dispatch("savetest", { description: null, notes: "", tags: [] });
|
|
2219
2313
|
}
|
|
2220
2314
|
restartComponent() {
|
|
2221
2315
|
this._step = "ask";
|
|
2222
2316
|
this.description = "";
|
|
2317
|
+
this.notes = "";
|
|
2223
2318
|
this.tags = [];
|
|
2224
2319
|
this.render();
|
|
2225
2320
|
}
|
|
@@ -2246,12 +2341,16 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2246
2341
|
this.shadow.getElementById("btn-yes")?.addEventListener("click", () => this.askSave());
|
|
2247
2342
|
this.shadow.getElementById("btn-no")?.addEventListener("click", () => this.cancel());
|
|
2248
2343
|
} else {
|
|
2249
|
-
this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.tags, this.t.bind(this))}`;
|
|
2344
|
+
this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.notes, this.tags, this.t.bind(this))}`;
|
|
2250
2345
|
const descInput = this.shadow.getElementById("desc-input");
|
|
2346
|
+
const notesInput = this.shadow.getElementById("notes-input");
|
|
2251
2347
|
const tagInput = this.shadow.getElementById("tag-input");
|
|
2252
2348
|
descInput.addEventListener("input", () => {
|
|
2253
2349
|
this.description = descInput.value;
|
|
2254
2350
|
});
|
|
2351
|
+
notesInput.addEventListener("input", () => {
|
|
2352
|
+
this.notes = notesInput.value;
|
|
2353
|
+
});
|
|
2255
2354
|
const tryAddTag = () => {
|
|
2256
2355
|
this.addTag(tagInput.value);
|
|
2257
2356
|
tagInput.value = "";
|
|
@@ -2357,15 +2456,124 @@ var TEST_EDITOR_STYLES = `
|
|
|
2357
2456
|
background: #0d1117; padding: 10px 14px;
|
|
2358
2457
|
border-top: 1px solid #21262d;
|
|
2359
2458
|
}
|
|
2360
|
-
.
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
.
|
|
2459
|
+
.test-notes {
|
|
2460
|
+
margin: 0 0 10px; padding: 8px 12px;
|
|
2461
|
+
background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);
|
|
2462
|
+
border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;
|
|
2463
|
+
line-height: 1.6; white-space: pre-wrap; word-break: break-word;
|
|
2464
|
+
}
|
|
2465
|
+
.code-preview {
|
|
2466
|
+
margin: 0; padding: 10px 12px; background: #161b22;
|
|
2467
|
+
border-radius: 6px; border: 1px solid #21262d;
|
|
2468
|
+
font-size: 11px; color: #c9d1d9; line-height: 1.7;
|
|
2469
|
+
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
2470
|
+
overflow-x: auto; white-space: pre;
|
|
2471
|
+
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
2472
|
+
}
|
|
2473
|
+
.code-preview::-webkit-scrollbar { height: 4px; }
|
|
2474
|
+
.code-preview::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
2475
|
+
.code-preview-icp { margin-top: 8px; }
|
|
2476
|
+
.sh-kw { color: #ff7b72; }
|
|
2477
|
+
.sh-bi { color: #d2a8ff; }
|
|
2478
|
+
.sh-str { color: #a5d6ff; }
|
|
2479
|
+
.sh-cmt { color: #8b949e; font-style: italic; }
|
|
2480
|
+
.sh-num { color: #79c0ff; }
|
|
2367
2481
|
`;
|
|
2368
2482
|
|
|
2483
|
+
// src/utils/syntax-highlight.utils.ts
|
|
2484
|
+
var KEYWORDS = /* @__PURE__ */ new Set([
|
|
2485
|
+
"describe",
|
|
2486
|
+
"it",
|
|
2487
|
+
"xit",
|
|
2488
|
+
"fit",
|
|
2489
|
+
"xdescribe",
|
|
2490
|
+
"fdescribe",
|
|
2491
|
+
"beforeEach",
|
|
2492
|
+
"afterEach",
|
|
2493
|
+
"before",
|
|
2494
|
+
"after",
|
|
2495
|
+
"context",
|
|
2496
|
+
"const",
|
|
2497
|
+
"let",
|
|
2498
|
+
"var",
|
|
2499
|
+
"function",
|
|
2500
|
+
"return",
|
|
2501
|
+
"if",
|
|
2502
|
+
"else",
|
|
2503
|
+
"import",
|
|
2504
|
+
"export",
|
|
2505
|
+
"from",
|
|
2506
|
+
"new",
|
|
2507
|
+
"this",
|
|
2508
|
+
"null",
|
|
2509
|
+
"undefined",
|
|
2510
|
+
"true",
|
|
2511
|
+
"false",
|
|
2512
|
+
"async",
|
|
2513
|
+
"await",
|
|
2514
|
+
"of",
|
|
2515
|
+
"in",
|
|
2516
|
+
"typeof",
|
|
2517
|
+
"void"
|
|
2518
|
+
]);
|
|
2519
|
+
var BUILTINS = /* @__PURE__ */ new Set(["cy", "expect", "assert", "Cypress", "chai"]);
|
|
2520
|
+
function syntaxHighlight(code) {
|
|
2521
|
+
return code.split("\n").map(highlightLine).join("\n");
|
|
2522
|
+
}
|
|
2523
|
+
function highlightLine(line) {
|
|
2524
|
+
let result = "";
|
|
2525
|
+
let i = 0;
|
|
2526
|
+
const len = line.length;
|
|
2527
|
+
while (i < len) {
|
|
2528
|
+
if (line[i] === "/" && i + 1 < len && line[i + 1] === "/") {
|
|
2529
|
+
result += `<span class="sh-cmt">${escHtml(line.slice(i))}</span>`;
|
|
2530
|
+
return result;
|
|
2531
|
+
}
|
|
2532
|
+
const q = line[i];
|
|
2533
|
+
if (q === "'" || q === '"' || q === "`") {
|
|
2534
|
+
let j = i + 1;
|
|
2535
|
+
while (j < len) {
|
|
2536
|
+
if (line[j] === "\\") {
|
|
2537
|
+
j += 2;
|
|
2538
|
+
continue;
|
|
2539
|
+
}
|
|
2540
|
+
if (line[j] === q) {
|
|
2541
|
+
j++;
|
|
2542
|
+
break;
|
|
2543
|
+
}
|
|
2544
|
+
j++;
|
|
2545
|
+
}
|
|
2546
|
+
result += `<span class="sh-str">${escHtml(line.slice(i, j))}</span>`;
|
|
2547
|
+
i = j;
|
|
2548
|
+
continue;
|
|
2549
|
+
}
|
|
2550
|
+
if (/[0-9]/.test(line[i]) && (i === 0 || !/[a-zA-Z_$]/.test(line[i - 1]))) {
|
|
2551
|
+
let j = i;
|
|
2552
|
+
while (j < len && /[0-9.]/.test(line[j])) j++;
|
|
2553
|
+
result += `<span class="sh-num">${escHtml(line.slice(i, j))}</span>`;
|
|
2554
|
+
i = j;
|
|
2555
|
+
continue;
|
|
2556
|
+
}
|
|
2557
|
+
if (/[a-zA-Z_$]/.test(line[i])) {
|
|
2558
|
+
let j = i;
|
|
2559
|
+
while (j < len && /[a-zA-Z0-9_$]/.test(line[j])) j++;
|
|
2560
|
+
const word = line.slice(i, j);
|
|
2561
|
+
if (KEYWORDS.has(word)) {
|
|
2562
|
+
result += `<span class="sh-kw">${escHtml(word)}</span>`;
|
|
2563
|
+
} else if (BUILTINS.has(word)) {
|
|
2564
|
+
result += `<span class="sh-bi">${escHtml(word)}</span>`;
|
|
2565
|
+
} else {
|
|
2566
|
+
result += escHtml(word);
|
|
2567
|
+
}
|
|
2568
|
+
i = j;
|
|
2569
|
+
continue;
|
|
2570
|
+
}
|
|
2571
|
+
result += escHtml(line[i]);
|
|
2572
|
+
i++;
|
|
2573
|
+
}
|
|
2574
|
+
return result;
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2369
2577
|
// src/components/test-editor/test-editor.template.ts
|
|
2370
2578
|
function renderTestEditor(state, t) {
|
|
2371
2579
|
const { tags, visible, selectedVisible, activeTag, selectMode, selectedIds, describeName, expandedIndex, interceptorsByTest } = state;
|
|
@@ -2383,18 +2591,20 @@ function renderTestEditor(state, t) {
|
|
|
2383
2591
|
const icps = interceptorsByTest[test.id] ?? test.interceptors ?? [];
|
|
2384
2592
|
const tagsHtml = (test.tags ?? []).length ? `<span class="test-tags">${(test.tags ?? []).map((tag) => `<span class="test-tag">${escHtml(tag)}</span>`).join("")}</span>` : "";
|
|
2385
2593
|
const checkbox = selectMode ? `<input type="checkbox" ${selectedIds.has(test.id) ? "checked" : ""} data-select="${test.id}" />` : "";
|
|
2594
|
+
const hasIcps = (test.interceptors ?? []).length > 0;
|
|
2595
|
+
const itBlockCode = `it('${test.name}', () => {
|
|
2596
|
+
${(test.commands ?? []).map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
2597
|
+
});`;
|
|
2598
|
+
const icpBlockCode = icps.length ? `beforeEach(() => {
|
|
2599
|
+
// Auto-generated Cypress interceptors
|
|
2600
|
+
${icps.map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
2601
|
+
});` : "";
|
|
2602
|
+
const notesHtml = expanded && test.notes ? `<p class="test-notes">${escHtml(test.notes)}</p>` : "";
|
|
2386
2603
|
const body = expanded ? `
|
|
2387
2604
|
<div class="row-body">
|
|
2388
|
-
|
|
2389
|
-
<
|
|
2390
|
-
${
|
|
2391
|
-
<div class="section-title" style="margin-top:8px">${t("TEST_EDITOR.SECTION_INTERCEPTORS")}</div>
|
|
2392
|
-
${icps.map(escHtml).join("<br>")}
|
|
2393
|
-
</div>` : ""}
|
|
2394
|
-
<div class="copy-row">
|
|
2395
|
-
<button class="btn-icon" data-action="copy-cmds" data-idx="${i}">${t("TEST_EDITOR.COPY_CMDS_BTN")}</button>
|
|
2396
|
-
${icps.length ? `<button class="btn-icon" data-action="copy-icps" data-idx="${i}">${t("TEST_EDITOR.COPY_ICPS_BTN")}</button>` : ""}
|
|
2397
|
-
</div>
|
|
2605
|
+
${notesHtml}
|
|
2606
|
+
<pre class="code-preview">${syntaxHighlight(itBlockCode)}</pre>
|
|
2607
|
+
${icpBlockCode ? `<pre class="code-preview code-preview-icp">${syntaxHighlight(icpBlockCode)}</pre>` : ""}
|
|
2398
2608
|
</div>` : "";
|
|
2399
2609
|
return `
|
|
2400
2610
|
<div class="row${selectedIds.has(test.id) ? " selected-row" : ""}">
|
|
@@ -2403,6 +2613,8 @@ function renderTestEditor(state, t) {
|
|
|
2403
2613
|
<span class="test-name">${escHtml(test.name)}</span>
|
|
2404
2614
|
${tagsHtml}
|
|
2405
2615
|
<span class="test-date">${date}</span>
|
|
2616
|
+
<button class="btn-icon" data-action="copy-cmds" data-idx="${i}" title="${t("TEST_EDITOR.COPY_CMDS_BTN")}">${t("TEST_EDITOR.COPY_CMDS_BTN")}</button>
|
|
2617
|
+
${hasIcps ? `<button class="btn-icon" data-action="copy-icps" data-idx="${i}" title="${t("TEST_EDITOR.COPY_ICPS_BTN")}">${t("TEST_EDITOR.COPY_ICPS_BTN")}</button>` : ""}
|
|
2406
2618
|
<button class="btn-icon btn-del" data-action="delete" data-id="${test.id}" title="${t("TEST_EDITOR.DELETE_TITLE")}">\u{1F5D1}</button>
|
|
2407
2619
|
</div>
|
|
2408
2620
|
${body}
|
|
@@ -2581,7 +2793,7 @@ ${beforeEach}${itBlocks}
|
|
|
2581
2793
|
ev.stopPropagation();
|
|
2582
2794
|
const idx = Number(el.dataset["idx"]);
|
|
2583
2795
|
const t = visible[idx];
|
|
2584
|
-
this.copyToClipboard((this.interceptorsByTest[t?.id] ?? []).join("\n"));
|
|
2796
|
+
this.copyToClipboard((this.interceptorsByTest[t?.id] ?? t?.interceptors ?? []).join("\n"));
|
|
2585
2797
|
});
|
|
2586
2798
|
});
|
|
2587
2799
|
}
|
|
@@ -2694,7 +2906,7 @@ var LANGS = [
|
|
|
2694
2906
|
{ value: "de", label: "Deutsch" }
|
|
2695
2907
|
];
|
|
2696
2908
|
function renderConfiguration(state, t) {
|
|
2697
|
-
const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled } = state;
|
|
2909
|
+
const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled, startHidden } = state;
|
|
2698
2910
|
const langOptions = LANGS.map(
|
|
2699
2911
|
(l) => `<option value="${l.value}" ${selectedLanguage === l.value ? "selected" : ""}>${l.label}</option>`
|
|
2700
2912
|
).join("");
|
|
@@ -2734,6 +2946,18 @@ function renderConfiguration(state, t) {
|
|
|
2734
2946
|
</label>
|
|
2735
2947
|
</div>
|
|
2736
2948
|
|
|
2949
|
+
<!-- Start Hidden -->
|
|
2950
|
+
<div class="card">
|
|
2951
|
+
<div class="card-hd">${t("CONFIG.START_HIDDEN_SECTION")}</div>
|
|
2952
|
+
<label class="check-row">
|
|
2953
|
+
<input type="checkbox" id="start-hidden-toggle" ${startHidden ? "checked" : ""} />
|
|
2954
|
+
<div>
|
|
2955
|
+
<div class="check-title">${t("CONFIG.START_HIDDEN_TITLE")}</div>
|
|
2956
|
+
<div class="check-sub">${t("CONFIG.START_HIDDEN_SUB")}</div>
|
|
2957
|
+
</div>
|
|
2958
|
+
</label>
|
|
2959
|
+
</div>
|
|
2960
|
+
|
|
2737
2961
|
<!-- Selector Strategy -->
|
|
2738
2962
|
<div class="card card-wide">
|
|
2739
2963
|
<div class="card-hd">${t("CONFIG.SELECTOR_SECTION")}</div>
|
|
@@ -2796,6 +3020,7 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
2796
3020
|
advancedHttpConfig = false;
|
|
2797
3021
|
selectorStrategy = "data-cy";
|
|
2798
3022
|
smartSelectorEnabled = true;
|
|
3023
|
+
startHidden = false;
|
|
2799
3024
|
filesystemGranted = false;
|
|
2800
3025
|
cypressFolderName = null;
|
|
2801
3026
|
constructor() {
|
|
@@ -2821,6 +3046,7 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
2821
3046
|
this.advancedHttpConfig = localStorage.getItem("extendedHttpCommands") === "true";
|
|
2822
3047
|
this.selectorStrategy = config?.["selectorStrategy"] ?? "data-cy";
|
|
2823
3048
|
this.smartSelectorEnabled = config?.["smartSelectorEnabled"] !== "false";
|
|
3049
|
+
this.startHidden = config?.["startHidden"] === "true";
|
|
2824
3050
|
this.filesystemGranted = config?.["allowReadWriteFiles"] === "true";
|
|
2825
3051
|
const handle = config?.["cypressDirectoryHandle"];
|
|
2826
3052
|
this.cypressFolderName = handle?.name ?? null;
|
|
@@ -2838,6 +3064,12 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
2838
3064
|
this.persistence.setConfig({ extendedHttpCommands: checked ? "true" : "false" });
|
|
2839
3065
|
this.render();
|
|
2840
3066
|
}
|
|
3067
|
+
async onStartHiddenChange(checked) {
|
|
3068
|
+
this.startHidden = checked;
|
|
3069
|
+
await this.persistence.setConfig({ startHidden: checked ? "true" : "false" });
|
|
3070
|
+
this.dispatchEvent(new CustomEvent("starthiddenchange", { detail: checked, bubbles: true, composed: true }));
|
|
3071
|
+
this.render();
|
|
3072
|
+
}
|
|
2841
3073
|
async onSmartSelectorChange(enabled) {
|
|
2842
3074
|
this.smartSelectorEnabled = enabled;
|
|
2843
3075
|
await this.persistence.setConfig({ smartSelectorEnabled: enabled ? "true" : "false" });
|
|
@@ -2898,7 +3130,8 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
2898
3130
|
selectorStrategy: this.selectorStrategy,
|
|
2899
3131
|
filesystemGranted: this.filesystemGranted,
|
|
2900
3132
|
cypressFolderName: this.cypressFolderName,
|
|
2901
|
-
smartSelectorEnabled: this.smartSelectorEnabled
|
|
3133
|
+
smartSelectorEnabled: this.smartSelectorEnabled,
|
|
3134
|
+
startHidden: this.startHidden
|
|
2902
3135
|
}, this.t.bind(this))}`;
|
|
2903
3136
|
;
|
|
2904
3137
|
this.shadow.getElementById("lang-select").addEventListener(
|
|
@@ -2913,6 +3146,10 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
2913
3146
|
"change",
|
|
2914
3147
|
(e) => this.onSmartSelectorChange(e.target.checked)
|
|
2915
3148
|
);
|
|
3149
|
+
this.shadow.getElementById("start-hidden-toggle").addEventListener(
|
|
3150
|
+
"change",
|
|
3151
|
+
(e) => this.onStartHiddenChange(e.target.checked)
|
|
3152
|
+
);
|
|
2916
3153
|
this.shadow.getElementById("selector-strategy").addEventListener(
|
|
2917
3154
|
"change",
|
|
2918
3155
|
(e) => this.onSelectorStrategyChange(e.target.value)
|
|
@@ -2944,26 +3181,38 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
2944
3181
|
* { box-sizing: border-box; }
|
|
2945
3182
|
.layout { display: flex; flex: 1; min-height: 0; }
|
|
2946
3183
|
.sidebar {
|
|
2947
|
-
|
|
2948
|
-
|
|
3184
|
+
border-right: none; display: flex; flex-direction: column;
|
|
3185
|
+
background: #0d1117; flex-shrink: 0; min-width: 140px; max-width: 500px;
|
|
3186
|
+
}
|
|
3187
|
+
.tree-scroll {
|
|
3188
|
+
flex: 1; overflow-y: auto; padding: 6px 4px;
|
|
2949
3189
|
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
2950
3190
|
}
|
|
2951
|
-
.
|
|
2952
|
-
.
|
|
2953
|
-
.
|
|
3191
|
+
.tree-scroll::-webkit-scrollbar { width: 4px; }
|
|
3192
|
+
.tree-scroll::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
3193
|
+
.resize-handle {
|
|
3194
|
+
width: 4px; background: #21262d; cursor: col-resize; flex-shrink: 0;
|
|
3195
|
+
transition: background 0.15s;
|
|
3196
|
+
}
|
|
3197
|
+
.resize-handle:hover, .resize-handle.dragging { background: #2f81f7; }
|
|
3198
|
+
.main { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #161b22; min-width: 0; }
|
|
2954
3199
|
.no-perm {
|
|
2955
3200
|
padding: 28px; color: #484f58; font-size: 13px; text-align: center;
|
|
2956
3201
|
display: flex; flex-direction: column; align-items: center; gap: 12px; line-height: 1.6;
|
|
2957
3202
|
}
|
|
2958
3203
|
.tree-item {
|
|
2959
|
-
padding:
|
|
3204
|
+
padding: 4px 6px; border-radius: 4px; cursor: pointer;
|
|
2960
3205
|
font-size: 12px; color: #8b949e; white-space: nowrap;
|
|
2961
3206
|
overflow: hidden; text-overflow: ellipsis;
|
|
2962
3207
|
transition: background 0.12s, color 0.12s;
|
|
3208
|
+
display: flex; align-items: center; gap: 4px; user-select: none;
|
|
2963
3209
|
}
|
|
2964
3210
|
.tree-item:hover { background: #161b22; color: #c9d1d9; }
|
|
2965
3211
|
.tree-item.selected { background: rgba(47,129,247,0.12); color: #2f81f7; }
|
|
2966
3212
|
.tree-item.dir { color: #e3b341; font-weight: 600; }
|
|
3213
|
+
.tree-item.dir:hover { background: rgba(227,179,65,0.08); color: #f0c040; }
|
|
3214
|
+
.dir-arrow { font-size: 8px; color: #484f58; width: 10px; flex-shrink: 0; line-height: 1; }
|
|
3215
|
+
.tree-connector { display: block; width: 1px; background: #21262d; margin-left: 13px; height: 100%; }
|
|
2967
3216
|
.content-area {
|
|
2968
3217
|
flex: 1; padding: 12px 14px; overflow-y: auto;
|
|
2969
3218
|
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
@@ -2973,12 +3222,21 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
2973
3222
|
.file-name { font-size: 11px; color: #484f58; margin-bottom: 8px; font-family: monospace; }
|
|
2974
3223
|
pre {
|
|
2975
3224
|
background: #0d1117; padding: 12px; border-radius: 8px;
|
|
2976
|
-
font-size: 11px; color: #c9d1d9;
|
|
2977
|
-
white-space: pre-wrap; word-break: break-all; margin: 0;
|
|
3225
|
+
font-size: 11px; color: #c9d1d9; margin: 0;
|
|
2978
3226
|
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
2979
|
-
line-height: 1.7;
|
|
2980
|
-
|
|
3227
|
+
line-height: 1.7; border: 1px solid #21262d;
|
|
3228
|
+
white-space: pre; overflow-x: auto; overflow-y: auto;
|
|
3229
|
+
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
2981
3230
|
}
|
|
3231
|
+
pre::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
3232
|
+
pre::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
3233
|
+
.pre-block { font-size: 10.5px; }
|
|
3234
|
+
.pre-icp .sh-str { color: #85e89d; }
|
|
3235
|
+
.sh-kw { color: #ff7b72; }
|
|
3236
|
+
.sh-bi { color: #d2a8ff; }
|
|
3237
|
+
.sh-str { color: #a5d6ff; }
|
|
3238
|
+
.sh-cmt { color: #8b949e; font-style: italic; }
|
|
3239
|
+
.sh-num { color: #79c0ff; }
|
|
2982
3240
|
.footer {
|
|
2983
3241
|
padding: 10px 14px; border-top: 1px solid #21262d;
|
|
2984
3242
|
display: flex; gap: 8px; justify-content: flex-end; background: #161b22;
|
|
@@ -2994,6 +3252,12 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
2994
3252
|
.btn-save:hover { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
2995
3253
|
.btn-save:disabled { background: #21262d; border-color: #30363d; color: #8b949e; }
|
|
2996
3254
|
.placeholder { color: #484f58; font-size: 13px; padding: 28px; text-align: center; }
|
|
3255
|
+
.test-notes {
|
|
3256
|
+
margin: 0 0 10px; padding: 8px 12px;
|
|
3257
|
+
background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);
|
|
3258
|
+
border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;
|
|
3259
|
+
line-height: 1.6; white-space: pre-wrap; word-break: break-word;
|
|
3260
|
+
}
|
|
2997
3261
|
.block-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
|
|
2998
3262
|
.btn-copy {
|
|
2999
3263
|
padding: 3px 10px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;
|
|
@@ -3001,6 +3265,34 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
3001
3265
|
transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;
|
|
3002
3266
|
}
|
|
3003
3267
|
.btn-copy:hover { background: #30363d; color: #e6edf3; }
|
|
3268
|
+
.sidebar-toolbar {
|
|
3269
|
+
display: flex; gap: 4px; padding: 6px 6px 4px;
|
|
3270
|
+
border-bottom: 1px solid #21262d; flex-shrink: 0; background: #0d1117;
|
|
3271
|
+
}
|
|
3272
|
+
.btn-toolbar {
|
|
3273
|
+
flex: 1; padding: 4px 6px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;
|
|
3274
|
+
font-size: 10px; font-weight: 500; background: #161b22; color: #8b949e;
|
|
3275
|
+
transition: background 0.12s, color 0.12s; white-space: nowrap; overflow: hidden;
|
|
3276
|
+
text-overflow: ellipsis;
|
|
3277
|
+
}
|
|
3278
|
+
.btn-toolbar:hover { background: #30363d; color: #e6edf3; }
|
|
3279
|
+
.btn-toolbar.btn-new { color: #3fb950; border-color: #238636; }
|
|
3280
|
+
.btn-toolbar.btn-new:hover { background: #238636; color: #fff; }
|
|
3281
|
+
.new-file-form {
|
|
3282
|
+
padding: 6px; border-bottom: 1px solid #21262d; display: flex; flex-direction: column; gap: 4px;
|
|
3283
|
+
}
|
|
3284
|
+
.new-file-form input {
|
|
3285
|
+
width: 100%; padding: 4px 7px; background: #0d1117; border: 1px solid #30363d;
|
|
3286
|
+
border-radius: 5px; color: #e6edf3; font-size: 11px; font-family: monospace;
|
|
3287
|
+
outline: none;
|
|
3288
|
+
}
|
|
3289
|
+
.new-file-form input:focus { border-color: #2f81f7; }
|
|
3290
|
+
.new-file-form .ext { font-size: 9px; color: #484f58; padding: 0 2px; }
|
|
3291
|
+
.new-file-actions { display: flex; gap: 4px; }
|
|
3292
|
+
.btn-confirm { flex: 1; padding: 3px 6px; border: 1px solid #238636; border-radius: 5px; cursor: pointer; font-size: 10px; font-weight: 500; background: #238636; color: #fff; transition: background 0.12s; }
|
|
3293
|
+
.btn-confirm:hover { background: #2ea043; }
|
|
3294
|
+
.btn-cancel-form { flex: 1; padding: 3px 6px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer; font-size: 10px; font-weight: 500; background: #21262d; color: #8b949e; transition: background 0.12s; }
|
|
3295
|
+
.btn-cancel-form:hover { background: #30363d; color: #e6edf3; }
|
|
3004
3296
|
`;
|
|
3005
3297
|
|
|
3006
3298
|
// src/components/advanced-test-editor/advanced-test-editor.template.ts
|
|
@@ -3018,29 +3310,48 @@ function renderNoPermission(needsReauth, t) {
|
|
|
3018
3310
|
</div>`;
|
|
3019
3311
|
}
|
|
3020
3312
|
function renderAdvancedEditor(state, t) {
|
|
3021
|
-
const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, saveButtonEnabled } = state;
|
|
3022
|
-
const treeHtml = e2eTree.length ? renderTree(e2eTree, selectedFile) : `<div class="tree-item" style="color:#6c7a99">${t("ADVANCED_EDITOR.NO_FILES")}</div>`;
|
|
3313
|
+
const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, testNotes, saveButtonEnabled, isCreatingFile, collapsedDirs, sidebarWidth } = state;
|
|
3314
|
+
const treeHtml = e2eTree.length ? renderTree(e2eTree, selectedFile, collapsedDirs) : `<div class="tree-item" style="color:#6c7a99">${t("ADVANCED_EDITOR.NO_FILES")}</div>`;
|
|
3023
3315
|
const contentHtml = selectedFileContent ? `<div class="file-name">\u{1F4C4} ${escHtml(selectedFile?.name ?? "")}</div>
|
|
3024
|
-
<pre>${
|
|
3316
|
+
<pre class="pre-file">${syntaxHighlight(selectedFileContent.slice(0, 6e3))}${selectedFileContent.length > 6e3 ? "\n..." : ""}</pre>` : `<div class="placeholder">${t("ADVANCED_EDITOR.SELECT_FILE")}</div>`;
|
|
3317
|
+
const notesHtml = testItBlock && testNotes ? `<p class="test-notes">${escHtml(testNotes)}</p>` : "";
|
|
3025
3318
|
const itHtml = testItBlock ? `<div style="margin-top:10px">
|
|
3026
3319
|
<div class="file-name block-header">
|
|
3027
3320
|
<span>${t("ADVANCED_EDITOR.IT_LABEL")}</span>
|
|
3028
3321
|
<button id="btn-copy-it" class="btn-copy">${t("ADVANCED_EDITOR.COPY_IT_BTN")}</button>
|
|
3029
3322
|
</div>
|
|
3030
|
-
<pre
|
|
3323
|
+
<pre class="pre-block">${syntaxHighlight(testItBlock.slice(0, 3e3))}</pre>
|
|
3031
3324
|
</div>` : "";
|
|
3032
3325
|
const interceptorsHtml = interceptorsBlock ? `<div style="margin-top:10px">
|
|
3033
3326
|
<div class="file-name block-header">
|
|
3034
3327
|
<span>${t("ADVANCED_EDITOR.BEFORE_EACH_LABEL")}</span>
|
|
3035
3328
|
<button id="btn-copy-interceptors" class="btn-copy">${t("ADVANCED_EDITOR.COPY_ICP_BTN")}</button>
|
|
3036
3329
|
</div>
|
|
3037
|
-
<pre
|
|
3330
|
+
<pre class="pre-block pre-icp">${syntaxHighlight(interceptorsBlock.slice(0, 3e3))}</pre>
|
|
3331
|
+
</div>` : "";
|
|
3332
|
+
const newFileForm = isCreatingFile ? `<div class="new-file-form">
|
|
3333
|
+
<input id="input-new-file" type="text" placeholder="${escHtml(t("ADVANCED_EDITOR.NEW_FILE_PLACEHOLDER"))}" autocomplete="off" />
|
|
3334
|
+
<span class="ext">.cy.ts</span>
|
|
3335
|
+
<div class="new-file-actions">
|
|
3336
|
+
<button id="btn-new-file-confirm" class="btn-confirm">${t("ADVANCED_EDITOR.NEW_FILE_CONFIRM")}</button>
|
|
3337
|
+
<button id="btn-new-file-cancel" class="btn-cancel-form">${t("ADVANCED_EDITOR.NEW_FILE_CANCEL")}</button>
|
|
3338
|
+
</div>
|
|
3038
3339
|
</div>` : "";
|
|
3340
|
+
const toolbar = `
|
|
3341
|
+
<div class="sidebar-toolbar">
|
|
3342
|
+
<button id="btn-new-file" class="btn-toolbar btn-new">${t("ADVANCED_EDITOR.NEW_FILE_BTN")}</button>
|
|
3343
|
+
<button id="btn-refresh" class="btn-toolbar">${t("ADVANCED_EDITOR.REFRESH_BTN")}</button>
|
|
3344
|
+
</div>`;
|
|
3039
3345
|
return `
|
|
3040
3346
|
<div class="layout">
|
|
3041
|
-
<div class="sidebar"
|
|
3347
|
+
<div class="sidebar" style="width:${sidebarWidth}px">
|
|
3348
|
+
${toolbar}
|
|
3349
|
+
${newFileForm}
|
|
3350
|
+
<div class="tree-scroll">${treeHtml}</div>
|
|
3351
|
+
</div>
|
|
3352
|
+
<div id="resize-handle" class="resize-handle"></div>
|
|
3042
3353
|
<div class="main">
|
|
3043
|
-
<div class="content-area">${contentHtml}${itHtml}${interceptorsHtml}</div>
|
|
3354
|
+
<div class="content-area">${contentHtml}${notesHtml}${itHtml}${interceptorsHtml}</div>
|
|
3044
3355
|
<div class="footer">
|
|
3045
3356
|
<button id="btn-save" class="btn-save"
|
|
3046
3357
|
${!saveButtonEnabled || !testItBlock ? "disabled" : ""}>
|
|
@@ -3054,16 +3365,24 @@ function renderAdvancedEditor(state, t) {
|
|
|
3054
3365
|
</div>
|
|
3055
3366
|
</div>`;
|
|
3056
3367
|
}
|
|
3057
|
-
function renderTree(nodes, selected, indent = 0) {
|
|
3368
|
+
function renderTree(nodes, selected, collapsedDirs, indent = 0, parentPath = "") {
|
|
3058
3369
|
return nodes.map((n) => {
|
|
3370
|
+
const currentPath = parentPath ? `${parentPath}/${n.name}` : n.name;
|
|
3059
3371
|
const isFile = n.kind === "file";
|
|
3060
|
-
const
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3372
|
+
const pad = `padding-left:${6 + indent * 14}px`;
|
|
3373
|
+
if (!isFile) {
|
|
3374
|
+
const dir = n;
|
|
3375
|
+
const hasChildren = (dir.children?.length ?? 0) > 0;
|
|
3376
|
+
const isCollapsed = collapsedDirs.has(currentPath);
|
|
3377
|
+
const arrow = hasChildren ? isCollapsed ? "\u25B6" : "\u25BC" : "\xB7";
|
|
3378
|
+
const dirHtml = `<div class="tree-item dir" style="${pad}" data-dir-path="${escAttr(currentPath)}">
|
|
3379
|
+
<span class="dir-arrow">${arrow}</span>\u{1F4C1} ${escHtml(n.name)}
|
|
3380
|
+
</div>`;
|
|
3381
|
+
if (!hasChildren || isCollapsed) return dirHtml;
|
|
3382
|
+
return dirHtml + renderTree(dir.children, selected, collapsedDirs, indent + 1, currentPath);
|
|
3066
3383
|
}
|
|
3384
|
+
const isSel = selected?.name === n.name;
|
|
3385
|
+
const cls = `tree-item${isSel ? " selected" : ""}`;
|
|
3067
3386
|
const data = JSON.stringify({ kind: n.kind, name: n.name }).replace(/"/g, """);
|
|
3068
3387
|
return `<div class="${cls}" style="${pad}" data-file="${data}">\u{1F4C4} ${escHtml(n.name)}</div>`;
|
|
3069
3388
|
}).join("");
|
|
@@ -3093,12 +3412,17 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3093
3412
|
selectedFileContent = null;
|
|
3094
3413
|
testItBlock = "";
|
|
3095
3414
|
interceptorsBlock = "";
|
|
3415
|
+
testNotes = "";
|
|
3096
3416
|
isPreviewMode = false;
|
|
3097
3417
|
previewFileName = null;
|
|
3098
3418
|
previewFileContent = null;
|
|
3419
|
+
isCreatingFile = false;
|
|
3420
|
+
collapsedDirs = /* @__PURE__ */ new Set();
|
|
3421
|
+
sidebarWidth = 220;
|
|
3099
3422
|
hasPermission = false;
|
|
3100
3423
|
needsReauth = false;
|
|
3101
3424
|
_dirHandle = null;
|
|
3425
|
+
_e2eHandle = null;
|
|
3102
3426
|
constructor() {
|
|
3103
3427
|
super();
|
|
3104
3428
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
@@ -3140,7 +3464,8 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3140
3464
|
try {
|
|
3141
3465
|
for await (const entry of this._dirHandle.values()) {
|
|
3142
3466
|
if (entry.kind === "directory" && entry.name === "e2e") {
|
|
3143
|
-
|
|
3467
|
+
this._e2eHandle = entry;
|
|
3468
|
+
const tree = await this.transformationService.scanDirectory(this._e2eHandle);
|
|
3144
3469
|
this.e2eTree = tree.children ?? [];
|
|
3145
3470
|
this.render();
|
|
3146
3471
|
return;
|
|
@@ -3149,13 +3474,40 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3149
3474
|
} catch {
|
|
3150
3475
|
}
|
|
3151
3476
|
}
|
|
3477
|
+
async createNewFile(rawName) {
|
|
3478
|
+
if (!this._e2eHandle) return;
|
|
3479
|
+
const name = rawName.trim().replace(/\.cy\.ts$/, "");
|
|
3480
|
+
if (!name) return;
|
|
3481
|
+
const fileName = `${name}.cy.ts`;
|
|
3482
|
+
const template = `describe('${name}', () => {
|
|
3483
|
+
|
|
3484
|
+
it('should ', () => {
|
|
3485
|
+
|
|
3486
|
+
});
|
|
3487
|
+
|
|
3488
|
+
});
|
|
3489
|
+
`;
|
|
3490
|
+
try {
|
|
3491
|
+
const fileHandle = await this._e2eHandle.getFileHandle(fileName, { create: true });
|
|
3492
|
+
const writable = await fileHandle.createWritable();
|
|
3493
|
+
await writable.write(template);
|
|
3494
|
+
await writable.close();
|
|
3495
|
+
} catch {
|
|
3496
|
+
}
|
|
3497
|
+
this.isCreatingFile = false;
|
|
3498
|
+
await this.getFoldersData();
|
|
3499
|
+
}
|
|
3500
|
+
async refreshTree() {
|
|
3501
|
+
await this.getFoldersData();
|
|
3502
|
+
}
|
|
3152
3503
|
async saveCommandsToFile() {
|
|
3153
3504
|
if (!this.selectedFileHandle || !this.selectedFileContent || !this.testItBlock) return;
|
|
3154
3505
|
let content = this.selectedFileContent;
|
|
3155
3506
|
if (this.interceptorsBlock) {
|
|
3156
3507
|
content = this.transformationService.insertBeforeEach(content, this.interceptorsBlock);
|
|
3157
3508
|
}
|
|
3158
|
-
|
|
3509
|
+
const comment = this.testNotes ? this.transformationService.buildBlockComment(this.testNotes) + "\n" : "";
|
|
3510
|
+
content = this.transformationService.insertItBlock(content, comment + this.testItBlock);
|
|
3159
3511
|
if (!content) return;
|
|
3160
3512
|
const writable = await this.selectedFileHandle.createWritable();
|
|
3161
3513
|
await writable.write(content);
|
|
@@ -3182,9 +3534,11 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3182
3534
|
if (test) {
|
|
3183
3535
|
this.testItBlock = test.itBlock ?? "";
|
|
3184
3536
|
this.interceptorsBlock = test.interceptorsBlock ?? "";
|
|
3537
|
+
this.testNotes = test.notes ?? "";
|
|
3185
3538
|
} else {
|
|
3186
3539
|
this.testItBlock = "";
|
|
3187
3540
|
this.interceptorsBlock = "";
|
|
3541
|
+
this.testNotes = "";
|
|
3188
3542
|
}
|
|
3189
3543
|
this.render();
|
|
3190
3544
|
}
|
|
@@ -3206,6 +3560,44 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3206
3560
|
composed: true
|
|
3207
3561
|
}));
|
|
3208
3562
|
}
|
|
3563
|
+
toggleDir(path) {
|
|
3564
|
+
if (this.collapsedDirs.has(path)) {
|
|
3565
|
+
this.collapsedDirs.delete(path);
|
|
3566
|
+
} else {
|
|
3567
|
+
this.collapsedDirs.add(path);
|
|
3568
|
+
}
|
|
3569
|
+
this.render();
|
|
3570
|
+
}
|
|
3571
|
+
setupResizeHandle() {
|
|
3572
|
+
const handle = this.shadow.getElementById("resize-handle");
|
|
3573
|
+
const sidebar = this.shadow.querySelector(".sidebar");
|
|
3574
|
+
if (!handle || !sidebar) return;
|
|
3575
|
+
let startX = 0;
|
|
3576
|
+
let startWidth = 0;
|
|
3577
|
+
const onMouseMove = (e) => {
|
|
3578
|
+
const delta = e.clientX - startX;
|
|
3579
|
+
const newWidth = Math.max(140, Math.min(500, startWidth + delta));
|
|
3580
|
+
this.sidebarWidth = newWidth;
|
|
3581
|
+
sidebar.style.width = `${newWidth}px`;
|
|
3582
|
+
};
|
|
3583
|
+
const onMouseUp = () => {
|
|
3584
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
3585
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
3586
|
+
document.body.style.cursor = "";
|
|
3587
|
+
document.body.style.userSelect = "";
|
|
3588
|
+
handle.classList.remove("dragging");
|
|
3589
|
+
};
|
|
3590
|
+
handle.addEventListener("mousedown", (e) => {
|
|
3591
|
+
startX = e.clientX;
|
|
3592
|
+
startWidth = sidebar.offsetWidth;
|
|
3593
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
3594
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
3595
|
+
document.body.style.cursor = "col-resize";
|
|
3596
|
+
document.body.style.userSelect = "none";
|
|
3597
|
+
handle.classList.add("dragging");
|
|
3598
|
+
e.preventDefault();
|
|
3599
|
+
});
|
|
3600
|
+
}
|
|
3209
3601
|
closePreview() {
|
|
3210
3602
|
this.isPreviewMode = false;
|
|
3211
3603
|
this.previewFileName = null;
|
|
@@ -3236,7 +3628,11 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3236
3628
|
selectedFileContent: this.selectedFileContent,
|
|
3237
3629
|
testItBlock: this.testItBlock,
|
|
3238
3630
|
interceptorsBlock: this.interceptorsBlock,
|
|
3239
|
-
|
|
3631
|
+
testNotes: this.testNotes,
|
|
3632
|
+
saveButtonEnabled: this.saveButtonEnabled,
|
|
3633
|
+
isCreatingFile: this.isCreatingFile,
|
|
3634
|
+
collapsedDirs: this.collapsedDirs,
|
|
3635
|
+
sidebarWidth: this.sidebarWidth
|
|
3240
3636
|
}, this.t.bind(this))}`;
|
|
3241
3637
|
this.shadow.querySelectorAll("[data-file]").forEach((el) => {
|
|
3242
3638
|
el.addEventListener("click", () => {
|
|
@@ -3244,11 +3640,41 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3244
3640
|
if (data) this.onFileClick(JSON.parse(data));
|
|
3245
3641
|
});
|
|
3246
3642
|
});
|
|
3643
|
+
this.shadow.querySelectorAll("[data-dir-path]").forEach((el) => {
|
|
3644
|
+
el.addEventListener("click", () => {
|
|
3645
|
+
const path = el.dataset["dirPath"];
|
|
3646
|
+
if (path) this.toggleDir(path);
|
|
3647
|
+
});
|
|
3648
|
+
});
|
|
3649
|
+
this.setupResizeHandle();
|
|
3247
3650
|
this.shadow.getElementById("btn-save")?.addEventListener("click", () => this.saveCommandsToFile());
|
|
3248
3651
|
this.shadow.getElementById("btn-edit")?.addEventListener("click", () => this.openEditManually());
|
|
3249
3652
|
this.shadow.getElementById("btn-copy-it")?.addEventListener("click", () => this.copyToClipboard(this.testItBlock));
|
|
3250
3653
|
this.shadow.getElementById("btn-copy-interceptors")?.addEventListener("click", () => this.copyToClipboard(this.interceptorsBlock));
|
|
3251
3654
|
this.shadow.getElementById("btn-close")?.addEventListener("click", () => this.closePreview());
|
|
3655
|
+
this.shadow.getElementById("btn-new-file")?.addEventListener("click", () => {
|
|
3656
|
+
this.isCreatingFile = !this.isCreatingFile;
|
|
3657
|
+
this.render();
|
|
3658
|
+
if (this.isCreatingFile) this.shadow.getElementById("input-new-file")?.focus();
|
|
3659
|
+
});
|
|
3660
|
+
this.shadow.getElementById("btn-refresh")?.addEventListener("click", () => this.refreshTree());
|
|
3661
|
+
this.shadow.getElementById("btn-new-file-confirm")?.addEventListener("click", () => {
|
|
3662
|
+
const input2 = this.shadow.getElementById("input-new-file");
|
|
3663
|
+
this.createNewFile(input2?.value ?? "");
|
|
3664
|
+
});
|
|
3665
|
+
this.shadow.getElementById("btn-new-file-cancel")?.addEventListener("click", () => {
|
|
3666
|
+
this.isCreatingFile = false;
|
|
3667
|
+
this.render();
|
|
3668
|
+
});
|
|
3669
|
+
const input = this.shadow.getElementById("input-new-file");
|
|
3670
|
+
input?.addEventListener("keydown", (e) => {
|
|
3671
|
+
if (e.key === "Enter") {
|
|
3672
|
+
this.createNewFile(input.value);
|
|
3673
|
+
} else if (e.key === "Escape") {
|
|
3674
|
+
this.isCreatingFile = false;
|
|
3675
|
+
this.render();
|
|
3676
|
+
}
|
|
3677
|
+
});
|
|
3252
3678
|
}
|
|
3253
3679
|
};
|
|
3254
3680
|
if (!customElements.get("advanced-test-editor")) {
|
|
@@ -3755,6 +4181,7 @@ function renderRecorderWidget(rec, paused, t) {
|
|
|
3755
4181
|
// src/components/lib-e2e-recorder/lib-e2e-recorder.ts
|
|
3756
4182
|
var LibE2eRecorderElement = class extends HTMLElement {
|
|
3757
4183
|
shadow;
|
|
4184
|
+
_isDisabled = false;
|
|
3758
4185
|
keydownHandler;
|
|
3759
4186
|
recordingUnsub;
|
|
3760
4187
|
commandsUnsub;
|
|
@@ -3768,6 +4195,7 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3768
4195
|
recording;
|
|
3769
4196
|
persistence;
|
|
3770
4197
|
translation;
|
|
4198
|
+
isVisible = false;
|
|
3771
4199
|
isRecording = false;
|
|
3772
4200
|
isPaused = false;
|
|
3773
4201
|
cypressCommands = [];
|
|
@@ -3782,6 +4210,10 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3782
4210
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
3783
4211
|
}
|
|
3784
4212
|
connectedCallback() {
|
|
4213
|
+
if ("Cypress" in window) {
|
|
4214
|
+
this._isDisabled = true;
|
|
4215
|
+
return;
|
|
4216
|
+
}
|
|
3785
4217
|
if (!this.getAttribute("data-cy")) {
|
|
3786
4218
|
this.setAttribute("data-cy", "lib-e2e-cypress-for-dummys");
|
|
3787
4219
|
}
|
|
@@ -3798,10 +4230,12 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3798
4230
|
this.initSelectorStrategy();
|
|
3799
4231
|
this.initSubscriptions();
|
|
3800
4232
|
this.render();
|
|
4233
|
+
this.initVisibility();
|
|
3801
4234
|
this.keydownHandler = (e) => this.handleKeyboardEvent(e);
|
|
3802
4235
|
window.addEventListener("keydown", this.keydownHandler);
|
|
3803
4236
|
}
|
|
3804
4237
|
disconnectedCallback() {
|
|
4238
|
+
if (this._isDisabled) return;
|
|
3805
4239
|
window.removeEventListener("keydown", this.keydownHandler);
|
|
3806
4240
|
this.recordingUnsub?.();
|
|
3807
4241
|
this.commandsUnsub?.();
|
|
@@ -3862,6 +4296,16 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3862
4296
|
document.body.appendChild(picker);
|
|
3863
4297
|
});
|
|
3864
4298
|
}
|
|
4299
|
+
async initVisibility() {
|
|
4300
|
+
if (this.hasAttribute("start-hidden")) {
|
|
4301
|
+
this.isVisible = this.getAttribute("start-hidden") === "false";
|
|
4302
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4303
|
+
return;
|
|
4304
|
+
}
|
|
4305
|
+
const config = await this.persistence.getGeneralConfig();
|
|
4306
|
+
this.isVisible = config?.["startHidden"] !== "true";
|
|
4307
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4308
|
+
}
|
|
3865
4309
|
async initSelectorStrategy() {
|
|
3866
4310
|
const config = await this.persistence.getGeneralConfig();
|
|
3867
4311
|
const strategy = config?.["selectorStrategy"];
|
|
@@ -3881,6 +4325,12 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3881
4325
|
handleKeyboardEvent(event) {
|
|
3882
4326
|
if (!event.ctrlKey) return;
|
|
3883
4327
|
const key = event.key.toLowerCase();
|
|
4328
|
+
if (key === "e" && event.shiftKey) {
|
|
4329
|
+
event.preventDefault();
|
|
4330
|
+
this.toggleVisibility();
|
|
4331
|
+
return;
|
|
4332
|
+
}
|
|
4333
|
+
if (!this.isVisible) return;
|
|
3884
4334
|
if (key === "r") {
|
|
3885
4335
|
event.preventDefault();
|
|
3886
4336
|
this.toggle();
|
|
@@ -3898,6 +4348,10 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
3898
4348
|
this.showSettingsDialog();
|
|
3899
4349
|
}
|
|
3900
4350
|
}
|
|
4351
|
+
toggleVisibility() {
|
|
4352
|
+
this.isVisible = !this.isVisible;
|
|
4353
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4354
|
+
}
|
|
3901
4355
|
// ── recording history (task 5) ────────────────────────────────────────────
|
|
3902
4356
|
saveRecordingHistory() {
|
|
3903
4357
|
if (!this.cypressCommands.length) return;
|
|
@@ -4133,13 +4587,13 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4133
4587
|
child.translation = this.translation;
|
|
4134
4588
|
container.appendChild(child);
|
|
4135
4589
|
child.addEventListener("savetest", (e) => {
|
|
4136
|
-
const { description, tags } = e.detail ?? {};
|
|
4137
|
-
this.onSaveTest(description ?? null, tags ?? []);
|
|
4590
|
+
const { description, notes, tags } = e.detail ?? {};
|
|
4591
|
+
this.onSaveTest(description ?? null, tags ?? [], notes ?? "");
|
|
4138
4592
|
Swal.close();
|
|
4139
4593
|
});
|
|
4140
4594
|
child.addEventListener("saveandexport", (e) => {
|
|
4141
|
-
const { description, tags } = e.detail ?? {};
|
|
4142
|
-
this.onSaveAndExportTest(description ?? null, tags ?? []);
|
|
4595
|
+
const { description, notes, tags } = e.detail ?? {};
|
|
4596
|
+
this.onSaveAndExportTest(description ?? null, tags ?? [], notes ?? "");
|
|
4143
4597
|
Swal.close();
|
|
4144
4598
|
});
|
|
4145
4599
|
},
|
|
@@ -4170,6 +4624,10 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4170
4624
|
child.addEventListener("smartselectorchange", (e) => {
|
|
4171
4625
|
this.smartSelectorEnabled = e.detail;
|
|
4172
4626
|
});
|
|
4627
|
+
child.addEventListener("starthiddenchange", (e) => {
|
|
4628
|
+
this.isVisible = !e.detail;
|
|
4629
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4630
|
+
});
|
|
4173
4631
|
},
|
|
4174
4632
|
willClose: () => {
|
|
4175
4633
|
this.isSettingsDialogOpen = false;
|
|
@@ -4182,7 +4640,7 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4182
4640
|
this.toggleModal("isAdvancedEditorDialogOpen", () => {
|
|
4183
4641
|
Swal.fire({
|
|
4184
4642
|
title: this.translation.translate("MAIN_FRAME.SHOW_ADVANCED_EDITOR"),
|
|
4185
|
-
html: '<div id="advanced-editor-modal-content" style="min-height:
|
|
4643
|
+
html: '<div id="advanced-editor-modal-content" style="flex:1;min-height:0;display:flex;flex-direction:column;padding:0"></div>',
|
|
4186
4644
|
showCloseButton: true,
|
|
4187
4645
|
showConfirmButton: false,
|
|
4188
4646
|
allowOutsideClick: false,
|
|
@@ -4191,6 +4649,20 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4191
4649
|
didOpen: () => {
|
|
4192
4650
|
makeSwalDraggable();
|
|
4193
4651
|
setSwal2DataCyAttribute();
|
|
4652
|
+
const popup = Swal.getPopup();
|
|
4653
|
+
if (popup) {
|
|
4654
|
+
popup.style.height = "600px";
|
|
4655
|
+
const htmlContainer = popup.querySelector(".swal2-html-container");
|
|
4656
|
+
if (htmlContainer) {
|
|
4657
|
+
htmlContainer.style.flex = "1";
|
|
4658
|
+
htmlContainer.style.minHeight = "0";
|
|
4659
|
+
htmlContainer.style.overflow = "hidden";
|
|
4660
|
+
htmlContainer.style.padding = "0";
|
|
4661
|
+
htmlContainer.style.margin = "0";
|
|
4662
|
+
htmlContainer.style.display = "flex";
|
|
4663
|
+
htmlContainer.style.flexDirection = "column";
|
|
4664
|
+
}
|
|
4665
|
+
}
|
|
4194
4666
|
const container = document.getElementById("advanced-editor-modal-content");
|
|
4195
4667
|
if (!container) return;
|
|
4196
4668
|
const child = document.createElement("advanced-test-editor");
|
|
@@ -4218,7 +4690,10 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4218
4690
|
this.isAdvancedEditorDialogOpen = false;
|
|
4219
4691
|
}
|
|
4220
4692
|
});
|
|
4221
|
-
|
|
4693
|
+
setTimeout(() => {
|
|
4694
|
+
const popup = Swal.getPopup();
|
|
4695
|
+
if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 0 });
|
|
4696
|
+
}, 0);
|
|
4222
4697
|
});
|
|
4223
4698
|
}
|
|
4224
4699
|
showFileEditorDialog(handle, content, fileName, testId, itBlock = "", interceptorsBlock = "") {
|
|
@@ -4264,18 +4739,18 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4264
4739
|
this.resizePopup();
|
|
4265
4740
|
}
|
|
4266
4741
|
// ── save handlers ─────────────────────────────────────────────────────────
|
|
4267
|
-
async onSaveTest(description, tags = []) {
|
|
4742
|
+
async onSaveTest(description, tags = [], notes = "") {
|
|
4268
4743
|
if (description) {
|
|
4269
|
-
await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags);
|
|
4744
|
+
await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);
|
|
4270
4745
|
this.recording.clearCommands();
|
|
4271
4746
|
this.clearRecordingHistory();
|
|
4272
4747
|
this.cypressCommands = [];
|
|
4273
4748
|
this.interceptors = [];
|
|
4274
4749
|
}
|
|
4275
4750
|
}
|
|
4276
|
-
async onSaveAndExportTest(description, tags = []) {
|
|
4751
|
+
async onSaveAndExportTest(description, tags = [], notes = "") {
|
|
4277
4752
|
if (description) {
|
|
4278
|
-
const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags);
|
|
4753
|
+
const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);
|
|
4279
4754
|
this.recording.clearCommands();
|
|
4280
4755
|
this.clearRecordingHistory();
|
|
4281
4756
|
this.cypressCommands = [];
|
|
@@ -4302,6 +4777,7 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4302
4777
|
render() {
|
|
4303
4778
|
const rec = this.isRecording;
|
|
4304
4779
|
const paused = this.isPaused;
|
|
4780
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4305
4781
|
this.shadow.innerHTML = `<style>${getRecorderStyles(rec, paused)}</style>${renderRecorderWidget(rec, paused, this.translation.translate.bind(this.translation))}`;
|
|
4306
4782
|
this.shadow.querySelector('[data-action="toggle"]')?.addEventListener("click", () => this.toggle());
|
|
4307
4783
|
this.shadow.querySelector('[data-action="pause"]')?.addEventListener("click", () => this.togglePause());
|