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.cjs
CHANGED
|
@@ -578,7 +578,9 @@ var I18N_ES = {
|
|
|
578
578
|
NO_TAGS: "Sin etiquetas",
|
|
579
579
|
SAVE_BTN: "\u{1F4BE} Guardar",
|
|
580
580
|
SAVE_AND_EDIT: "\u{1F4DD} Guardar y editar",
|
|
581
|
-
REMOVE_TAG_TITLE: "Quitar"
|
|
581
|
+
REMOVE_TAG_TITLE: "Quitar",
|
|
582
|
+
NOTES_LABEL: "Descripci\xF3n / Notas (opcional):",
|
|
583
|
+
NOTES_PLACEHOLDER: "Qu\xE9 valida este test, condiciones previas, etc."
|
|
582
584
|
},
|
|
583
585
|
TEST_EDITOR: {
|
|
584
586
|
NO_TAGS: "Sin etiquetas",
|
|
@@ -627,7 +629,10 @@ var I18N_ES = {
|
|
|
627
629
|
JSON_BAD_FORMAT: "El archivo no tiene el formato esperado.",
|
|
628
630
|
SMART_SELECTOR_SECTION: "\u{1F50D} Selector inteligente",
|
|
629
631
|
SMART_SELECTOR_TITLE: "Selector inteligente",
|
|
630
|
-
SMART_SELECTOR_SUB: "Muestra un picker al hacer click en elementos sin selector v\xE1lido."
|
|
632
|
+
SMART_SELECTOR_SUB: "Muestra un picker al hacer click en elementos sin selector v\xE1lido.",
|
|
633
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilidad del widget",
|
|
634
|
+
START_HIDDEN_TITLE: "Iniciar oculto",
|
|
635
|
+
START_HIDDEN_SUB: "El widget arranca invisible. Usa Ctrl+Shift+E para mostrarlo u ocultarlo."
|
|
631
636
|
},
|
|
632
637
|
SELECTOR_PICKER: {
|
|
633
638
|
TITLE: "Selecciona un elemento del DOM",
|
|
@@ -666,7 +671,12 @@ var I18N_ES = {
|
|
|
666
671
|
COPY_ICP_BTN: "\u{1F4CB} Copiar interceptores",
|
|
667
672
|
INSERT_BTN: "\u{1F4BE} Insertar en archivo",
|
|
668
673
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Editar manualmente",
|
|
669
|
-
CLOSE_BTN: "\u2715 Cerrar"
|
|
674
|
+
CLOSE_BTN: "\u2715 Cerrar",
|
|
675
|
+
NEW_FILE_BTN: "+ Nuevo archivo",
|
|
676
|
+
REFRESH_BTN: "\u21BB Actualizar",
|
|
677
|
+
NEW_FILE_PLACEHOLDER: "nombre-del-test",
|
|
678
|
+
NEW_FILE_CONFIRM: "Crear",
|
|
679
|
+
NEW_FILE_CANCEL: "Cancelar"
|
|
670
680
|
},
|
|
671
681
|
FILE_PREVIEW: {
|
|
672
682
|
NO_FILE: "Sin archivo",
|
|
@@ -735,7 +745,9 @@ var I18N_EN = {
|
|
|
735
745
|
NO_TAGS: "No tags",
|
|
736
746
|
SAVE_BTN: "\u{1F4BE} Save",
|
|
737
747
|
SAVE_AND_EDIT: "\u{1F4DD} Save and edit",
|
|
738
|
-
REMOVE_TAG_TITLE: "Remove"
|
|
748
|
+
REMOVE_TAG_TITLE: "Remove",
|
|
749
|
+
NOTES_LABEL: "Description / Notes (optional):",
|
|
750
|
+
NOTES_PLACEHOLDER: "What this test validates, preconditions, etc."
|
|
739
751
|
},
|
|
740
752
|
TEST_EDITOR: {
|
|
741
753
|
NO_TAGS: "No tags",
|
|
@@ -784,7 +796,10 @@ var I18N_EN = {
|
|
|
784
796
|
JSON_BAD_FORMAT: "The file does not have the expected format.",
|
|
785
797
|
SMART_SELECTOR_SECTION: "\u{1F50D} Smart selector",
|
|
786
798
|
SMART_SELECTOR_TITLE: "Smart selector",
|
|
787
|
-
SMART_SELECTOR_SUB: "Shows a picker when clicking elements with no valid selector."
|
|
799
|
+
SMART_SELECTOR_SUB: "Shows a picker when clicking elements with no valid selector.",
|
|
800
|
+
START_HIDDEN_SECTION: "\u{1F441} Widget visibility",
|
|
801
|
+
START_HIDDEN_TITLE: "Start hidden",
|
|
802
|
+
START_HIDDEN_SUB: "The widget starts invisible. Use Ctrl+Shift+E to show or hide it."
|
|
788
803
|
},
|
|
789
804
|
SELECTOR_PICKER: {
|
|
790
805
|
TITLE: "Select a DOM element",
|
|
@@ -823,7 +838,12 @@ var I18N_EN = {
|
|
|
823
838
|
COPY_ICP_BTN: "\u{1F4CB} Copy interceptors",
|
|
824
839
|
INSERT_BTN: "\u{1F4BE} Insert into file",
|
|
825
840
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Edit manually",
|
|
826
|
-
CLOSE_BTN: "\u2715 Close"
|
|
841
|
+
CLOSE_BTN: "\u2715 Close",
|
|
842
|
+
NEW_FILE_BTN: "+ New file",
|
|
843
|
+
REFRESH_BTN: "\u21BB Refresh",
|
|
844
|
+
NEW_FILE_PLACEHOLDER: "test-name",
|
|
845
|
+
NEW_FILE_CONFIRM: "Create",
|
|
846
|
+
NEW_FILE_CANCEL: "Cancel"
|
|
827
847
|
},
|
|
828
848
|
FILE_PREVIEW: {
|
|
829
849
|
NO_FILE: "No file",
|
|
@@ -892,7 +912,9 @@ var I18N_FR = {
|
|
|
892
912
|
NO_TAGS: "Sans \xE9tiquettes",
|
|
893
913
|
SAVE_BTN: "\u{1F4BE} Enregistrer",
|
|
894
914
|
SAVE_AND_EDIT: "\u{1F4DD} Enregistrer et \xE9diter",
|
|
895
|
-
REMOVE_TAG_TITLE: "Retirer"
|
|
915
|
+
REMOVE_TAG_TITLE: "Retirer",
|
|
916
|
+
NOTES_LABEL: "Description / Notes (optionnel) :",
|
|
917
|
+
NOTES_PLACEHOLDER: "Ce que ce test valide, conditions pr\xE9alables, etc."
|
|
896
918
|
},
|
|
897
919
|
TEST_EDITOR: {
|
|
898
920
|
NO_TAGS: "Sans \xE9tiquettes",
|
|
@@ -941,7 +963,10 @@ var I18N_FR = {
|
|
|
941
963
|
JSON_BAD_FORMAT: "Le fichier n'a pas le format attendu.",
|
|
942
964
|
SMART_SELECTOR_SECTION: "\u{1F50D} S\xE9lecteur intelligent",
|
|
943
965
|
SMART_SELECTOR_TITLE: "S\xE9lecteur intelligent",
|
|
944
|
-
SMART_SELECTOR_SUB: "Affiche un s\xE9lecteur lors du clic sur des \xE9l\xE9ments sans s\xE9lecteur valide."
|
|
966
|
+
SMART_SELECTOR_SUB: "Affiche un s\xE9lecteur lors du clic sur des \xE9l\xE9ments sans s\xE9lecteur valide.",
|
|
967
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilit\xE9 du widget",
|
|
968
|
+
START_HIDDEN_TITLE: "D\xE9marrer masqu\xE9",
|
|
969
|
+
START_HIDDEN_SUB: "Le widget d\xE9marre invisible. Utilisez Ctrl+Shift+E pour l'afficher ou le masquer."
|
|
945
970
|
},
|
|
946
971
|
SELECTOR_PICKER: {
|
|
947
972
|
TITLE: "S\xE9lectionnez un \xE9l\xE9ment du DOM",
|
|
@@ -980,7 +1005,12 @@ var I18N_FR = {
|
|
|
980
1005
|
COPY_ICP_BTN: "\u{1F4CB} Copier les intercepteurs",
|
|
981
1006
|
INSERT_BTN: "\u{1F4BE} Ins\xE9rer dans le fichier",
|
|
982
1007
|
EDIT_MANUAL_BTN: "\u270F\uFE0F \xC9diter manuellement",
|
|
983
|
-
CLOSE_BTN: "\u2715 Fermer"
|
|
1008
|
+
CLOSE_BTN: "\u2715 Fermer",
|
|
1009
|
+
NEW_FILE_BTN: "+ Nouveau fichier",
|
|
1010
|
+
REFRESH_BTN: "\u21BB Actualiser",
|
|
1011
|
+
NEW_FILE_PLACEHOLDER: "nom-du-test",
|
|
1012
|
+
NEW_FILE_CONFIRM: "Cr\xE9er",
|
|
1013
|
+
NEW_FILE_CANCEL: "Annuler"
|
|
984
1014
|
},
|
|
985
1015
|
FILE_PREVIEW: {
|
|
986
1016
|
NO_FILE: "Sans fichier",
|
|
@@ -1049,7 +1079,9 @@ var I18N_IT = {
|
|
|
1049
1079
|
NO_TAGS: "Nessuna etichetta",
|
|
1050
1080
|
SAVE_BTN: "\u{1F4BE} Salva",
|
|
1051
1081
|
SAVE_AND_EDIT: "\u{1F4DD} Salva e modifica",
|
|
1052
|
-
REMOVE_TAG_TITLE: "Rimuovi"
|
|
1082
|
+
REMOVE_TAG_TITLE: "Rimuovi",
|
|
1083
|
+
NOTES_LABEL: "Descrizione / Note (opzionale):",
|
|
1084
|
+
NOTES_PLACEHOLDER: "Cosa valida questo test, condizioni preliminari, ecc."
|
|
1053
1085
|
},
|
|
1054
1086
|
TEST_EDITOR: {
|
|
1055
1087
|
NO_TAGS: "Nessuna etichetta",
|
|
@@ -1098,7 +1130,10 @@ var I18N_IT = {
|
|
|
1098
1130
|
JSON_BAD_FORMAT: "Il file non ha il formato previsto.",
|
|
1099
1131
|
SMART_SELECTOR_SECTION: "\u{1F50D} Selettore intelligente",
|
|
1100
1132
|
SMART_SELECTOR_TITLE: "Selettore intelligente",
|
|
1101
|
-
SMART_SELECTOR_SUB: "Mostra un selettore quando si fa clic su elementi senza selettore valido."
|
|
1133
|
+
SMART_SELECTOR_SUB: "Mostra un selettore quando si fa clic su elementi senza selettore valido.",
|
|
1134
|
+
START_HIDDEN_SECTION: "\u{1F441} Visibilit\xE0 del widget",
|
|
1135
|
+
START_HIDDEN_TITLE: "Avvia nascosto",
|
|
1136
|
+
START_HIDDEN_SUB: "Il widget si avvia invisibile. Usa Ctrl+Shift+E per mostrarlo o nasconderlo."
|
|
1102
1137
|
},
|
|
1103
1138
|
SELECTOR_PICKER: {
|
|
1104
1139
|
TITLE: "Seleziona un elemento DOM",
|
|
@@ -1137,7 +1172,12 @@ var I18N_IT = {
|
|
|
1137
1172
|
COPY_ICP_BTN: "\u{1F4CB} Copia interceptor",
|
|
1138
1173
|
INSERT_BTN: "\u{1F4BE} Inserisci nel file",
|
|
1139
1174
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Modifica manualmente",
|
|
1140
|
-
CLOSE_BTN: "\u2715 Chiudi"
|
|
1175
|
+
CLOSE_BTN: "\u2715 Chiudi",
|
|
1176
|
+
NEW_FILE_BTN: "+ Nuovo file",
|
|
1177
|
+
REFRESH_BTN: "\u21BB Aggiorna",
|
|
1178
|
+
NEW_FILE_PLACEHOLDER: "nome-del-test",
|
|
1179
|
+
NEW_FILE_CONFIRM: "Crea",
|
|
1180
|
+
NEW_FILE_CANCEL: "Annulla"
|
|
1141
1181
|
},
|
|
1142
1182
|
FILE_PREVIEW: {
|
|
1143
1183
|
NO_FILE: "Nessun file",
|
|
@@ -1206,7 +1246,9 @@ var I18N_DE = {
|
|
|
1206
1246
|
NO_TAGS: "Keine Tags",
|
|
1207
1247
|
SAVE_BTN: "\u{1F4BE} Speichern",
|
|
1208
1248
|
SAVE_AND_EDIT: "\u{1F4DD} Speichern und bearbeiten",
|
|
1209
|
-
REMOVE_TAG_TITLE: "Entfernen"
|
|
1249
|
+
REMOVE_TAG_TITLE: "Entfernen",
|
|
1250
|
+
NOTES_LABEL: "Beschreibung / Notizen (optional):",
|
|
1251
|
+
NOTES_PLACEHOLDER: "Was dieser Test validiert, Voraussetzungen usw."
|
|
1210
1252
|
},
|
|
1211
1253
|
TEST_EDITOR: {
|
|
1212
1254
|
NO_TAGS: "Keine Tags",
|
|
@@ -1255,7 +1297,10 @@ var I18N_DE = {
|
|
|
1255
1297
|
JSON_BAD_FORMAT: "Die Datei hat nicht das erwartete Format.",
|
|
1256
1298
|
SMART_SELECTOR_SECTION: "\u{1F50D} Intelligenter Selektor",
|
|
1257
1299
|
SMART_SELECTOR_TITLE: "Intelligenter Selektor",
|
|
1258
|
-
SMART_SELECTOR_SUB: "Zeigt ein Auswahlfeld, wenn auf Elemente ohne g\xFCltigen Selektor geklickt wird."
|
|
1300
|
+
SMART_SELECTOR_SUB: "Zeigt ein Auswahlfeld, wenn auf Elemente ohne g\xFCltigen Selektor geklickt wird.",
|
|
1301
|
+
START_HIDDEN_SECTION: "\u{1F441} Widget-Sichtbarkeit",
|
|
1302
|
+
START_HIDDEN_TITLE: "Versteckt starten",
|
|
1303
|
+
START_HIDDEN_SUB: "Das Widget startet unsichtbar. Verwenden Sie Ctrl+Shift+E zum Ein-/Ausblenden."
|
|
1259
1304
|
},
|
|
1260
1305
|
SELECTOR_PICKER: {
|
|
1261
1306
|
TITLE: "DOM-Element ausw\xE4hlen",
|
|
@@ -1294,7 +1339,12 @@ var I18N_DE = {
|
|
|
1294
1339
|
COPY_ICP_BTN: "\u{1F4CB} Interceptors kopieren",
|
|
1295
1340
|
INSERT_BTN: "\u{1F4BE} In Datei einf\xFCgen",
|
|
1296
1341
|
EDIT_MANUAL_BTN: "\u270F\uFE0F Manuell bearbeiten",
|
|
1297
|
-
CLOSE_BTN: "\u2715 Schlie\xDFen"
|
|
1342
|
+
CLOSE_BTN: "\u2715 Schlie\xDFen",
|
|
1343
|
+
NEW_FILE_BTN: "+ Neue Datei",
|
|
1344
|
+
REFRESH_BTN: "\u21BB Aktualisieren",
|
|
1345
|
+
NEW_FILE_PLACEHOLDER: "test-name",
|
|
1346
|
+
NEW_FILE_CONFIRM: "Erstellen",
|
|
1347
|
+
NEW_FILE_CANCEL: "Abbrechen"
|
|
1298
1348
|
},
|
|
1299
1349
|
FILE_PREVIEW: {
|
|
1300
1350
|
NO_FILE: "Keine Datei",
|
|
@@ -1376,13 +1426,37 @@ var TranslationService = class {
|
|
|
1376
1426
|
};
|
|
1377
1427
|
var translationService = new TranslationService();
|
|
1378
1428
|
|
|
1429
|
+
// src/utils/code-format.utils.ts
|
|
1430
|
+
function gcd(a, b) {
|
|
1431
|
+
while (b) {
|
|
1432
|
+
const t = b;
|
|
1433
|
+
b = a % b;
|
|
1434
|
+
a = t;
|
|
1435
|
+
}
|
|
1436
|
+
return a;
|
|
1437
|
+
}
|
|
1438
|
+
function normalizeBlock(code, baseIndent) {
|
|
1439
|
+
const lines = code.split("\n").map((l) => l.trimEnd());
|
|
1440
|
+
const nonEmpty = lines.filter((l) => l.trim().length > 0);
|
|
1441
|
+
if (!nonEmpty.length) return "";
|
|
1442
|
+
const indents = nonEmpty.map((l) => l.length - l.trimStart().length);
|
|
1443
|
+
const minIndent = Math.min(...indents);
|
|
1444
|
+
const relIndents = [...new Set(indents.map((n) => n - minIndent).filter((n) => n > 0))];
|
|
1445
|
+
const step = relIndents.length > 0 ? relIndents.reduce(gcd) : 2;
|
|
1446
|
+
return lines.map((l) => {
|
|
1447
|
+
if (!l.trim()) return "";
|
|
1448
|
+
const level = Math.round((l.length - l.trimStart().length - minIndent) / step);
|
|
1449
|
+
return baseIndent + " ".repeat(level) + l.trimStart();
|
|
1450
|
+
}).join("\n");
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1379
1453
|
// src/services/transformation.service.ts
|
|
1380
1454
|
var TransformationService = class {
|
|
1381
1455
|
toLang(lang) {
|
|
1382
1456
|
return isLang(lang) ? lang : "en";
|
|
1383
1457
|
}
|
|
1384
1458
|
generateItDescription(description, commands) {
|
|
1385
|
-
const commandsBlock = commands.map((cmd) =>
|
|
1459
|
+
const commandsBlock = commands.map((cmd) => normalizeBlock(cmd, " ")).join("\n");
|
|
1386
1460
|
return `it('${description}', () => {
|
|
1387
1461
|
${commandsBlock}
|
|
1388
1462
|
});`;
|
|
@@ -1413,6 +1487,13 @@ ${interceptors} })
|
|
|
1413
1487
|
}
|
|
1414
1488
|
return content.slice(0, idx) + "\n" + itBlock + "\n" + content.slice(idx);
|
|
1415
1489
|
}
|
|
1490
|
+
buildBlockComment(notes) {
|
|
1491
|
+
if (!notes.trim()) return "";
|
|
1492
|
+
const lines = notes.split("\n").map((l) => ` * ${l}`).join("\n");
|
|
1493
|
+
return `/**
|
|
1494
|
+
${lines}
|
|
1495
|
+
*/`;
|
|
1496
|
+
}
|
|
1416
1497
|
isFile(file) {
|
|
1417
1498
|
return !!file && file.kind === "file";
|
|
1418
1499
|
}
|
|
@@ -1824,9 +1905,9 @@ var PersistenceService = class {
|
|
|
1824
1905
|
return this._db;
|
|
1825
1906
|
}
|
|
1826
1907
|
// ── Tests ─────────────────────────────────────────────────────────────────
|
|
1827
|
-
async insertTest(name, commands = [], interceptors = [], tags = []) {
|
|
1908
|
+
async insertTest(name, commands = [], interceptors = [], tags = [], notes) {
|
|
1828
1909
|
const db = await this.getDB();
|
|
1829
|
-
const record = { name, createdAt: Date.now(), ...tags.length ? { tags } : {} };
|
|
1910
|
+
const record = { name, createdAt: Date.now(), ...tags.length ? { tags } : {}, ...notes ? { notes } : {} };
|
|
1830
1911
|
const id = await db.add("tests", record);
|
|
1831
1912
|
if (commands.length) await this.insertCommands(commands, id);
|
|
1832
1913
|
if (interceptors.length) await this.insertInterceptors(interceptors, id);
|
|
@@ -1850,9 +1931,9 @@ var PersistenceService = class {
|
|
|
1850
1931
|
const commands = await this.getCommandStrings(testId);
|
|
1851
1932
|
const interceptors = await this.getInterceptorStrings(testId);
|
|
1852
1933
|
const itBlock = `it('${record.name}', () => {
|
|
1853
|
-
|
|
1934
|
+
${commands.map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
1854
1935
|
});`;
|
|
1855
|
-
const interceptorsBlock = interceptors.length ? " // Auto-generated Cypress interceptors\n" + interceptors.map((i) => " "
|
|
1936
|
+
const interceptorsBlock = interceptors.length ? " // Auto-generated Cypress interceptors\n" + interceptors.map((i) => normalizeBlock(i, " ")).join("\n") + "\n" : "";
|
|
1856
1937
|
return { ...record, commands, interceptors, cypressCommands: commands, itBlock, interceptorsBlock };
|
|
1857
1938
|
}
|
|
1858
1939
|
async deleteTest(id) {
|
|
@@ -2592,7 +2673,8 @@ if (!customElements.get("test-previsualizer")) {
|
|
|
2592
2673
|
var SAVE_TEST_STYLES = `
|
|
2593
2674
|
:host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }
|
|
2594
2675
|
* { box-sizing: border-box; }
|
|
2595
|
-
.container { padding: 24px 28px; text-align:
|
|
2676
|
+
.container { padding: 24px 28px; text-align: left; }
|
|
2677
|
+
.btn-row, p { text-align: center; }
|
|
2596
2678
|
p { margin: 0 0 20px; font-size: 14px; color: #8b949e; line-height: 1.5; }
|
|
2597
2679
|
.btn-row { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }
|
|
2598
2680
|
button {
|
|
@@ -2614,6 +2696,15 @@ var SAVE_TEST_STYLES = `
|
|
|
2614
2696
|
}
|
|
2615
2697
|
input[type="text"]:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }
|
|
2616
2698
|
input[type="text"]::placeholder { color: #484f58; }
|
|
2699
|
+
textarea {
|
|
2700
|
+
width: 100%; padding: 10px 14px; border: 1px solid #30363d;
|
|
2701
|
+
border-radius: 8px; background: #0d1117; color: #e6edf3;
|
|
2702
|
+
font-size: 14px; outline: none; margin-bottom: 4px;
|
|
2703
|
+
font-family: inherit; resize: vertical; line-height: 1.5;
|
|
2704
|
+
transition: border-color 0.15s, box-shadow 0.15s;
|
|
2705
|
+
}
|
|
2706
|
+
textarea:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }
|
|
2707
|
+
textarea::placeholder { color: #484f58; }
|
|
2617
2708
|
.tag-label {
|
|
2618
2709
|
font-size: 11px; color: #484f58; text-align: left; margin-bottom: 5px; display: block;
|
|
2619
2710
|
}
|
|
@@ -2653,7 +2744,7 @@ function renderSaveTestAsk(t) {
|
|
|
2653
2744
|
</div>
|
|
2654
2745
|
</div>`;
|
|
2655
2746
|
}
|
|
2656
|
-
function renderSaveTestDesc(description, tags, t) {
|
|
2747
|
+
function renderSaveTestDesc(description, notes, tags, t) {
|
|
2657
2748
|
const chipsHtml = tags.map(
|
|
2658
2749
|
(tag) => `<span class="chip">${escHtml(tag)}<button class="chip-del" data-tag="${escAttr(tag)}" title="${t("SAVE_TEST.REMOVE_TAG_TITLE")}">\u2715</button></span>`
|
|
2659
2750
|
).join("");
|
|
@@ -2662,6 +2753,8 @@ function renderSaveTestDesc(description, tags, t) {
|
|
|
2662
2753
|
<p>${t("SAVE_TEST.DESC_LABEL")} (<code>it()</code>):</p>
|
|
2663
2754
|
<input id="desc-input" type="text" placeholder="${t("SAVE_TEST.DESC_PLACEHOLDER")}"
|
|
2664
2755
|
value="${escAttr(description)}" autocomplete="off" />
|
|
2756
|
+
<span class="tag-label">${t("SAVE_TEST.NOTES_LABEL")}</span>
|
|
2757
|
+
<textarea id="notes-input" rows="3" placeholder="${escAttr(t("SAVE_TEST.NOTES_PLACEHOLDER"))}">${escHtml(notes)}</textarea>
|
|
2665
2758
|
<span class="tag-label">${t("SAVE_TEST.TAGS_LABEL")}</span>
|
|
2666
2759
|
<div class="tag-input-row">
|
|
2667
2760
|
<input id="tag-input" type="text" placeholder="${t("SAVE_TEST.TAGS_PLACEHOLDER")}" autocomplete="off" />
|
|
@@ -2681,6 +2774,7 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2681
2774
|
shadow;
|
|
2682
2775
|
_step = "ask";
|
|
2683
2776
|
description = "";
|
|
2777
|
+
notes = "";
|
|
2684
2778
|
tags = [];
|
|
2685
2779
|
translation = translationService;
|
|
2686
2780
|
constructor() {
|
|
@@ -2698,17 +2792,18 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2698
2792
|
this.render();
|
|
2699
2793
|
}
|
|
2700
2794
|
confirmSave() {
|
|
2701
|
-
this.dispatch("savetest", { description: this.description.trim(), tags: [...this.tags] });
|
|
2795
|
+
this.dispatch("savetest", { description: this.description.trim(), notes: this.notes, tags: [...this.tags] });
|
|
2702
2796
|
}
|
|
2703
2797
|
confirmSaveAndExport() {
|
|
2704
|
-
this.dispatch("saveandexport", { description: this.description.trim(), tags: [...this.tags] });
|
|
2798
|
+
this.dispatch("saveandexport", { description: this.description.trim(), notes: this.notes, tags: [...this.tags] });
|
|
2705
2799
|
}
|
|
2706
2800
|
cancel() {
|
|
2707
|
-
this.dispatch("savetest", { description: null, tags: [] });
|
|
2801
|
+
this.dispatch("savetest", { description: null, notes: "", tags: [] });
|
|
2708
2802
|
}
|
|
2709
2803
|
restartComponent() {
|
|
2710
2804
|
this._step = "ask";
|
|
2711
2805
|
this.description = "";
|
|
2806
|
+
this.notes = "";
|
|
2712
2807
|
this.tags = [];
|
|
2713
2808
|
this.render();
|
|
2714
2809
|
}
|
|
@@ -2735,12 +2830,16 @@ var SaveTestElement = class extends HTMLElement {
|
|
|
2735
2830
|
this.shadow.getElementById("btn-yes")?.addEventListener("click", () => this.askSave());
|
|
2736
2831
|
this.shadow.getElementById("btn-no")?.addEventListener("click", () => this.cancel());
|
|
2737
2832
|
} else {
|
|
2738
|
-
this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.tags, this.t.bind(this))}`;
|
|
2833
|
+
this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.notes, this.tags, this.t.bind(this))}`;
|
|
2739
2834
|
const descInput = this.shadow.getElementById("desc-input");
|
|
2835
|
+
const notesInput = this.shadow.getElementById("notes-input");
|
|
2740
2836
|
const tagInput = this.shadow.getElementById("tag-input");
|
|
2741
2837
|
descInput.addEventListener("input", () => {
|
|
2742
2838
|
this.description = descInput.value;
|
|
2743
2839
|
});
|
|
2840
|
+
notesInput.addEventListener("input", () => {
|
|
2841
|
+
this.notes = notesInput.value;
|
|
2842
|
+
});
|
|
2744
2843
|
const tryAddTag = () => {
|
|
2745
2844
|
this.addTag(tagInput.value);
|
|
2746
2845
|
tagInput.value = "";
|
|
@@ -2846,17 +2945,129 @@ var TEST_EDITOR_STYLES = `
|
|
|
2846
2945
|
background: #0d1117; padding: 10px 14px;
|
|
2847
2946
|
border-top: 1px solid #21262d;
|
|
2848
2947
|
}
|
|
2849
|
-
.
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
.
|
|
2948
|
+
.test-notes {
|
|
2949
|
+
margin: 0 0 10px; padding: 8px 12px;
|
|
2950
|
+
background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);
|
|
2951
|
+
border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;
|
|
2952
|
+
line-height: 1.6; white-space: pre-wrap; word-break: break-word;
|
|
2953
|
+
}
|
|
2954
|
+
.code-preview {
|
|
2955
|
+
margin: 0; padding: 10px 12px; background: #161b22;
|
|
2956
|
+
border-radius: 6px; border: 1px solid #21262d;
|
|
2957
|
+
font-size: 11px; color: #c9d1d9; line-height: 1.7;
|
|
2958
|
+
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
2959
|
+
overflow-x: auto; white-space: pre;
|
|
2960
|
+
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
2961
|
+
}
|
|
2962
|
+
.code-preview::-webkit-scrollbar { height: 4px; }
|
|
2963
|
+
.code-preview::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
2964
|
+
.code-preview-icp { margin-top: 8px; }
|
|
2965
|
+
.sh-kw { color: #ff7b72; }
|
|
2966
|
+
.sh-bi { color: #d2a8ff; }
|
|
2967
|
+
.sh-str { color: #a5d6ff; }
|
|
2968
|
+
.sh-cmt { color: #8b949e; font-style: italic; }
|
|
2969
|
+
.sh-num { color: #79c0ff; }
|
|
2856
2970
|
`;
|
|
2857
2971
|
|
|
2858
2972
|
// src/components/test-editor/test-editor.template.ts
|
|
2859
2973
|
init_html_utils();
|
|
2974
|
+
|
|
2975
|
+
// src/utils/syntax-highlight.utils.ts
|
|
2976
|
+
init_html_utils();
|
|
2977
|
+
var KEYWORDS = /* @__PURE__ */ new Set([
|
|
2978
|
+
"describe",
|
|
2979
|
+
"it",
|
|
2980
|
+
"xit",
|
|
2981
|
+
"fit",
|
|
2982
|
+
"xdescribe",
|
|
2983
|
+
"fdescribe",
|
|
2984
|
+
"beforeEach",
|
|
2985
|
+
"afterEach",
|
|
2986
|
+
"before",
|
|
2987
|
+
"after",
|
|
2988
|
+
"context",
|
|
2989
|
+
"const",
|
|
2990
|
+
"let",
|
|
2991
|
+
"var",
|
|
2992
|
+
"function",
|
|
2993
|
+
"return",
|
|
2994
|
+
"if",
|
|
2995
|
+
"else",
|
|
2996
|
+
"import",
|
|
2997
|
+
"export",
|
|
2998
|
+
"from",
|
|
2999
|
+
"new",
|
|
3000
|
+
"this",
|
|
3001
|
+
"null",
|
|
3002
|
+
"undefined",
|
|
3003
|
+
"true",
|
|
3004
|
+
"false",
|
|
3005
|
+
"async",
|
|
3006
|
+
"await",
|
|
3007
|
+
"of",
|
|
3008
|
+
"in",
|
|
3009
|
+
"typeof",
|
|
3010
|
+
"void"
|
|
3011
|
+
]);
|
|
3012
|
+
var BUILTINS = /* @__PURE__ */ new Set(["cy", "expect", "assert", "Cypress", "chai"]);
|
|
3013
|
+
function syntaxHighlight(code) {
|
|
3014
|
+
return code.split("\n").map(highlightLine).join("\n");
|
|
3015
|
+
}
|
|
3016
|
+
function highlightLine(line) {
|
|
3017
|
+
let result = "";
|
|
3018
|
+
let i = 0;
|
|
3019
|
+
const len = line.length;
|
|
3020
|
+
while (i < len) {
|
|
3021
|
+
if (line[i] === "/" && i + 1 < len && line[i + 1] === "/") {
|
|
3022
|
+
result += `<span class="sh-cmt">${escHtml(line.slice(i))}</span>`;
|
|
3023
|
+
return result;
|
|
3024
|
+
}
|
|
3025
|
+
const q = line[i];
|
|
3026
|
+
if (q === "'" || q === '"' || q === "`") {
|
|
3027
|
+
let j = i + 1;
|
|
3028
|
+
while (j < len) {
|
|
3029
|
+
if (line[j] === "\\") {
|
|
3030
|
+
j += 2;
|
|
3031
|
+
continue;
|
|
3032
|
+
}
|
|
3033
|
+
if (line[j] === q) {
|
|
3034
|
+
j++;
|
|
3035
|
+
break;
|
|
3036
|
+
}
|
|
3037
|
+
j++;
|
|
3038
|
+
}
|
|
3039
|
+
result += `<span class="sh-str">${escHtml(line.slice(i, j))}</span>`;
|
|
3040
|
+
i = j;
|
|
3041
|
+
continue;
|
|
3042
|
+
}
|
|
3043
|
+
if (/[0-9]/.test(line[i]) && (i === 0 || !/[a-zA-Z_$]/.test(line[i - 1]))) {
|
|
3044
|
+
let j = i;
|
|
3045
|
+
while (j < len && /[0-9.]/.test(line[j])) j++;
|
|
3046
|
+
result += `<span class="sh-num">${escHtml(line.slice(i, j))}</span>`;
|
|
3047
|
+
i = j;
|
|
3048
|
+
continue;
|
|
3049
|
+
}
|
|
3050
|
+
if (/[a-zA-Z_$]/.test(line[i])) {
|
|
3051
|
+
let j = i;
|
|
3052
|
+
while (j < len && /[a-zA-Z0-9_$]/.test(line[j])) j++;
|
|
3053
|
+
const word = line.slice(i, j);
|
|
3054
|
+
if (KEYWORDS.has(word)) {
|
|
3055
|
+
result += `<span class="sh-kw">${escHtml(word)}</span>`;
|
|
3056
|
+
} else if (BUILTINS.has(word)) {
|
|
3057
|
+
result += `<span class="sh-bi">${escHtml(word)}</span>`;
|
|
3058
|
+
} else {
|
|
3059
|
+
result += escHtml(word);
|
|
3060
|
+
}
|
|
3061
|
+
i = j;
|
|
3062
|
+
continue;
|
|
3063
|
+
}
|
|
3064
|
+
result += escHtml(line[i]);
|
|
3065
|
+
i++;
|
|
3066
|
+
}
|
|
3067
|
+
return result;
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
// src/components/test-editor/test-editor.template.ts
|
|
2860
3071
|
function renderTestEditor(state, t) {
|
|
2861
3072
|
const { tags, visible, selectedVisible, activeTag, selectMode, selectedIds, describeName, expandedIndex, interceptorsByTest } = state;
|
|
2862
3073
|
const tagFilterHtml = tags.length ? `<div class="tag-filter">
|
|
@@ -2873,18 +3084,20 @@ function renderTestEditor(state, t) {
|
|
|
2873
3084
|
const icps = interceptorsByTest[test.id] ?? test.interceptors ?? [];
|
|
2874
3085
|
const tagsHtml = (test.tags ?? []).length ? `<span class="test-tags">${(test.tags ?? []).map((tag) => `<span class="test-tag">${escHtml(tag)}</span>`).join("")}</span>` : "";
|
|
2875
3086
|
const checkbox = selectMode ? `<input type="checkbox" ${selectedIds.has(test.id) ? "checked" : ""} data-select="${test.id}" />` : "";
|
|
3087
|
+
const hasIcps = (test.interceptors ?? []).length > 0;
|
|
3088
|
+
const itBlockCode = `it('${test.name}', () => {
|
|
3089
|
+
${(test.commands ?? []).map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
3090
|
+
});`;
|
|
3091
|
+
const icpBlockCode = icps.length ? `beforeEach(() => {
|
|
3092
|
+
// Auto-generated Cypress interceptors
|
|
3093
|
+
${icps.map((c) => normalizeBlock(c, " ")).join("\n")}
|
|
3094
|
+
});` : "";
|
|
3095
|
+
const notesHtml = expanded && test.notes ? `<p class="test-notes">${escHtml(test.notes)}</p>` : "";
|
|
2876
3096
|
const body = expanded ? `
|
|
2877
3097
|
<div class="row-body">
|
|
2878
|
-
|
|
2879
|
-
<
|
|
2880
|
-
${
|
|
2881
|
-
<div class="section-title" style="margin-top:8px">${t("TEST_EDITOR.SECTION_INTERCEPTORS")}</div>
|
|
2882
|
-
${icps.map(escHtml).join("<br>")}
|
|
2883
|
-
</div>` : ""}
|
|
2884
|
-
<div class="copy-row">
|
|
2885
|
-
<button class="btn-icon" data-action="copy-cmds" data-idx="${i}">${t("TEST_EDITOR.COPY_CMDS_BTN")}</button>
|
|
2886
|
-
${icps.length ? `<button class="btn-icon" data-action="copy-icps" data-idx="${i}">${t("TEST_EDITOR.COPY_ICPS_BTN")}</button>` : ""}
|
|
2887
|
-
</div>
|
|
3098
|
+
${notesHtml}
|
|
3099
|
+
<pre class="code-preview">${syntaxHighlight(itBlockCode)}</pre>
|
|
3100
|
+
${icpBlockCode ? `<pre class="code-preview code-preview-icp">${syntaxHighlight(icpBlockCode)}</pre>` : ""}
|
|
2888
3101
|
</div>` : "";
|
|
2889
3102
|
return `
|
|
2890
3103
|
<div class="row${selectedIds.has(test.id) ? " selected-row" : ""}">
|
|
@@ -2893,6 +3106,8 @@ function renderTestEditor(state, t) {
|
|
|
2893
3106
|
<span class="test-name">${escHtml(test.name)}</span>
|
|
2894
3107
|
${tagsHtml}
|
|
2895
3108
|
<span class="test-date">${date}</span>
|
|
3109
|
+
<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>
|
|
3110
|
+
${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>` : ""}
|
|
2896
3111
|
<button class="btn-icon btn-del" data-action="delete" data-id="${test.id}" title="${t("TEST_EDITOR.DELETE_TITLE")}">\u{1F5D1}</button>
|
|
2897
3112
|
</div>
|
|
2898
3113
|
${body}
|
|
@@ -3071,7 +3286,7 @@ ${beforeEach}${itBlocks}
|
|
|
3071
3286
|
ev.stopPropagation();
|
|
3072
3287
|
const idx = Number(el.dataset["idx"]);
|
|
3073
3288
|
const t = visible[idx];
|
|
3074
|
-
this.copyToClipboard((this.interceptorsByTest[t?.id] ?? []).join("\n"));
|
|
3289
|
+
this.copyToClipboard((this.interceptorsByTest[t?.id] ?? t?.interceptors ?? []).join("\n"));
|
|
3075
3290
|
});
|
|
3076
3291
|
});
|
|
3077
3292
|
}
|
|
@@ -3184,7 +3399,7 @@ var LANGS = [
|
|
|
3184
3399
|
{ value: "de", label: "Deutsch" }
|
|
3185
3400
|
];
|
|
3186
3401
|
function renderConfiguration(state, t) {
|
|
3187
|
-
const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled } = state;
|
|
3402
|
+
const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled, startHidden } = state;
|
|
3188
3403
|
const langOptions = LANGS.map(
|
|
3189
3404
|
(l) => `<option value="${l.value}" ${selectedLanguage === l.value ? "selected" : ""}>${l.label}</option>`
|
|
3190
3405
|
).join("");
|
|
@@ -3224,6 +3439,18 @@ function renderConfiguration(state, t) {
|
|
|
3224
3439
|
</label>
|
|
3225
3440
|
</div>
|
|
3226
3441
|
|
|
3442
|
+
<!-- Start Hidden -->
|
|
3443
|
+
<div class="card">
|
|
3444
|
+
<div class="card-hd">${t("CONFIG.START_HIDDEN_SECTION")}</div>
|
|
3445
|
+
<label class="check-row">
|
|
3446
|
+
<input type="checkbox" id="start-hidden-toggle" ${startHidden ? "checked" : ""} />
|
|
3447
|
+
<div>
|
|
3448
|
+
<div class="check-title">${t("CONFIG.START_HIDDEN_TITLE")}</div>
|
|
3449
|
+
<div class="check-sub">${t("CONFIG.START_HIDDEN_SUB")}</div>
|
|
3450
|
+
</div>
|
|
3451
|
+
</label>
|
|
3452
|
+
</div>
|
|
3453
|
+
|
|
3227
3454
|
<!-- Selector Strategy -->
|
|
3228
3455
|
<div class="card card-wide">
|
|
3229
3456
|
<div class="card-hd">${t("CONFIG.SELECTOR_SECTION")}</div>
|
|
@@ -3286,6 +3513,7 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
3286
3513
|
advancedHttpConfig = false;
|
|
3287
3514
|
selectorStrategy = "data-cy";
|
|
3288
3515
|
smartSelectorEnabled = true;
|
|
3516
|
+
startHidden = false;
|
|
3289
3517
|
filesystemGranted = false;
|
|
3290
3518
|
cypressFolderName = null;
|
|
3291
3519
|
constructor() {
|
|
@@ -3311,6 +3539,7 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
3311
3539
|
this.advancedHttpConfig = localStorage.getItem("extendedHttpCommands") === "true";
|
|
3312
3540
|
this.selectorStrategy = config?.["selectorStrategy"] ?? "data-cy";
|
|
3313
3541
|
this.smartSelectorEnabled = config?.["smartSelectorEnabled"] !== "false";
|
|
3542
|
+
this.startHidden = config?.["startHidden"] === "true";
|
|
3314
3543
|
this.filesystemGranted = config?.["allowReadWriteFiles"] === "true";
|
|
3315
3544
|
const handle = config?.["cypressDirectoryHandle"];
|
|
3316
3545
|
this.cypressFolderName = handle?.name ?? null;
|
|
@@ -3328,6 +3557,12 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
3328
3557
|
this.persistence.setConfig({ extendedHttpCommands: checked ? "true" : "false" });
|
|
3329
3558
|
this.render();
|
|
3330
3559
|
}
|
|
3560
|
+
async onStartHiddenChange(checked) {
|
|
3561
|
+
this.startHidden = checked;
|
|
3562
|
+
await this.persistence.setConfig({ startHidden: checked ? "true" : "false" });
|
|
3563
|
+
this.dispatchEvent(new CustomEvent("starthiddenchange", { detail: checked, bubbles: true, composed: true }));
|
|
3564
|
+
this.render();
|
|
3565
|
+
}
|
|
3331
3566
|
async onSmartSelectorChange(enabled) {
|
|
3332
3567
|
this.smartSelectorEnabled = enabled;
|
|
3333
3568
|
await this.persistence.setConfig({ smartSelectorEnabled: enabled ? "true" : "false" });
|
|
@@ -3388,7 +3623,8 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
3388
3623
|
selectorStrategy: this.selectorStrategy,
|
|
3389
3624
|
filesystemGranted: this.filesystemGranted,
|
|
3390
3625
|
cypressFolderName: this.cypressFolderName,
|
|
3391
|
-
smartSelectorEnabled: this.smartSelectorEnabled
|
|
3626
|
+
smartSelectorEnabled: this.smartSelectorEnabled,
|
|
3627
|
+
startHidden: this.startHidden
|
|
3392
3628
|
}, this.t.bind(this))}`;
|
|
3393
3629
|
;
|
|
3394
3630
|
this.shadow.getElementById("lang-select").addEventListener(
|
|
@@ -3403,6 +3639,10 @@ var ConfigurationElement = class extends HTMLElement {
|
|
|
3403
3639
|
"change",
|
|
3404
3640
|
(e) => this.onSmartSelectorChange(e.target.checked)
|
|
3405
3641
|
);
|
|
3642
|
+
this.shadow.getElementById("start-hidden-toggle").addEventListener(
|
|
3643
|
+
"change",
|
|
3644
|
+
(e) => this.onStartHiddenChange(e.target.checked)
|
|
3645
|
+
);
|
|
3406
3646
|
this.shadow.getElementById("selector-strategy").addEventListener(
|
|
3407
3647
|
"change",
|
|
3408
3648
|
(e) => this.onSelectorStrategyChange(e.target.value)
|
|
@@ -3434,26 +3674,38 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
3434
3674
|
* { box-sizing: border-box; }
|
|
3435
3675
|
.layout { display: flex; flex: 1; min-height: 0; }
|
|
3436
3676
|
.sidebar {
|
|
3437
|
-
|
|
3438
|
-
|
|
3677
|
+
border-right: none; display: flex; flex-direction: column;
|
|
3678
|
+
background: #0d1117; flex-shrink: 0; min-width: 140px; max-width: 500px;
|
|
3679
|
+
}
|
|
3680
|
+
.tree-scroll {
|
|
3681
|
+
flex: 1; overflow-y: auto; padding: 6px 4px;
|
|
3439
3682
|
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
3440
3683
|
}
|
|
3441
|
-
.
|
|
3442
|
-
.
|
|
3443
|
-
.
|
|
3684
|
+
.tree-scroll::-webkit-scrollbar { width: 4px; }
|
|
3685
|
+
.tree-scroll::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
3686
|
+
.resize-handle {
|
|
3687
|
+
width: 4px; background: #21262d; cursor: col-resize; flex-shrink: 0;
|
|
3688
|
+
transition: background 0.15s;
|
|
3689
|
+
}
|
|
3690
|
+
.resize-handle:hover, .resize-handle.dragging { background: #2f81f7; }
|
|
3691
|
+
.main { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #161b22; min-width: 0; }
|
|
3444
3692
|
.no-perm {
|
|
3445
3693
|
padding: 28px; color: #484f58; font-size: 13px; text-align: center;
|
|
3446
3694
|
display: flex; flex-direction: column; align-items: center; gap: 12px; line-height: 1.6;
|
|
3447
3695
|
}
|
|
3448
3696
|
.tree-item {
|
|
3449
|
-
padding:
|
|
3697
|
+
padding: 4px 6px; border-radius: 4px; cursor: pointer;
|
|
3450
3698
|
font-size: 12px; color: #8b949e; white-space: nowrap;
|
|
3451
3699
|
overflow: hidden; text-overflow: ellipsis;
|
|
3452
3700
|
transition: background 0.12s, color 0.12s;
|
|
3701
|
+
display: flex; align-items: center; gap: 4px; user-select: none;
|
|
3453
3702
|
}
|
|
3454
3703
|
.tree-item:hover { background: #161b22; color: #c9d1d9; }
|
|
3455
3704
|
.tree-item.selected { background: rgba(47,129,247,0.12); color: #2f81f7; }
|
|
3456
3705
|
.tree-item.dir { color: #e3b341; font-weight: 600; }
|
|
3706
|
+
.tree-item.dir:hover { background: rgba(227,179,65,0.08); color: #f0c040; }
|
|
3707
|
+
.dir-arrow { font-size: 8px; color: #484f58; width: 10px; flex-shrink: 0; line-height: 1; }
|
|
3708
|
+
.tree-connector { display: block; width: 1px; background: #21262d; margin-left: 13px; height: 100%; }
|
|
3457
3709
|
.content-area {
|
|
3458
3710
|
flex: 1; padding: 12px 14px; overflow-y: auto;
|
|
3459
3711
|
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
@@ -3463,12 +3715,21 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
3463
3715
|
.file-name { font-size: 11px; color: #484f58; margin-bottom: 8px; font-family: monospace; }
|
|
3464
3716
|
pre {
|
|
3465
3717
|
background: #0d1117; padding: 12px; border-radius: 8px;
|
|
3466
|
-
font-size: 11px; color: #c9d1d9;
|
|
3467
|
-
white-space: pre-wrap; word-break: break-all; margin: 0;
|
|
3718
|
+
font-size: 11px; color: #c9d1d9; margin: 0;
|
|
3468
3719
|
font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;
|
|
3469
|
-
line-height: 1.7;
|
|
3470
|
-
|
|
3720
|
+
line-height: 1.7; border: 1px solid #21262d;
|
|
3721
|
+
white-space: pre; overflow-x: auto; overflow-y: auto;
|
|
3722
|
+
scrollbar-width: thin; scrollbar-color: #30363d transparent;
|
|
3471
3723
|
}
|
|
3724
|
+
pre::-webkit-scrollbar { width: 4px; height: 4px; }
|
|
3725
|
+
pre::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }
|
|
3726
|
+
.pre-block { font-size: 10.5px; }
|
|
3727
|
+
.pre-icp .sh-str { color: #85e89d; }
|
|
3728
|
+
.sh-kw { color: #ff7b72; }
|
|
3729
|
+
.sh-bi { color: #d2a8ff; }
|
|
3730
|
+
.sh-str { color: #a5d6ff; }
|
|
3731
|
+
.sh-cmt { color: #8b949e; font-style: italic; }
|
|
3732
|
+
.sh-num { color: #79c0ff; }
|
|
3472
3733
|
.footer {
|
|
3473
3734
|
padding: 10px 14px; border-top: 1px solid #21262d;
|
|
3474
3735
|
display: flex; gap: 8px; justify-content: flex-end; background: #161b22;
|
|
@@ -3484,6 +3745,12 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
3484
3745
|
.btn-save:hover { background: #1f6feb; border-color: #1f6feb; color: #fff; }
|
|
3485
3746
|
.btn-save:disabled { background: #21262d; border-color: #30363d; color: #8b949e; }
|
|
3486
3747
|
.placeholder { color: #484f58; font-size: 13px; padding: 28px; text-align: center; }
|
|
3748
|
+
.test-notes {
|
|
3749
|
+
margin: 0 0 10px; padding: 8px 12px;
|
|
3750
|
+
background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);
|
|
3751
|
+
border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;
|
|
3752
|
+
line-height: 1.6; white-space: pre-wrap; word-break: break-word;
|
|
3753
|
+
}
|
|
3487
3754
|
.block-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
|
|
3488
3755
|
.btn-copy {
|
|
3489
3756
|
padding: 3px 10px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;
|
|
@@ -3491,6 +3758,34 @@ var ADVANCED_TEST_EDITOR_STYLES = `
|
|
|
3491
3758
|
transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;
|
|
3492
3759
|
}
|
|
3493
3760
|
.btn-copy:hover { background: #30363d; color: #e6edf3; }
|
|
3761
|
+
.sidebar-toolbar {
|
|
3762
|
+
display: flex; gap: 4px; padding: 6px 6px 4px;
|
|
3763
|
+
border-bottom: 1px solid #21262d; flex-shrink: 0; background: #0d1117;
|
|
3764
|
+
}
|
|
3765
|
+
.btn-toolbar {
|
|
3766
|
+
flex: 1; padding: 4px 6px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;
|
|
3767
|
+
font-size: 10px; font-weight: 500; background: #161b22; color: #8b949e;
|
|
3768
|
+
transition: background 0.12s, color 0.12s; white-space: nowrap; overflow: hidden;
|
|
3769
|
+
text-overflow: ellipsis;
|
|
3770
|
+
}
|
|
3771
|
+
.btn-toolbar:hover { background: #30363d; color: #e6edf3; }
|
|
3772
|
+
.btn-toolbar.btn-new { color: #3fb950; border-color: #238636; }
|
|
3773
|
+
.btn-toolbar.btn-new:hover { background: #238636; color: #fff; }
|
|
3774
|
+
.new-file-form {
|
|
3775
|
+
padding: 6px; border-bottom: 1px solid #21262d; display: flex; flex-direction: column; gap: 4px;
|
|
3776
|
+
}
|
|
3777
|
+
.new-file-form input {
|
|
3778
|
+
width: 100%; padding: 4px 7px; background: #0d1117; border: 1px solid #30363d;
|
|
3779
|
+
border-radius: 5px; color: #e6edf3; font-size: 11px; font-family: monospace;
|
|
3780
|
+
outline: none;
|
|
3781
|
+
}
|
|
3782
|
+
.new-file-form input:focus { border-color: #2f81f7; }
|
|
3783
|
+
.new-file-form .ext { font-size: 9px; color: #484f58; padding: 0 2px; }
|
|
3784
|
+
.new-file-actions { display: flex; gap: 4px; }
|
|
3785
|
+
.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; }
|
|
3786
|
+
.btn-confirm:hover { background: #2ea043; }
|
|
3787
|
+
.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; }
|
|
3788
|
+
.btn-cancel-form:hover { background: #30363d; color: #e6edf3; }
|
|
3494
3789
|
`;
|
|
3495
3790
|
|
|
3496
3791
|
// src/components/advanced-test-editor/advanced-test-editor.template.ts
|
|
@@ -3509,29 +3804,48 @@ function renderNoPermission(needsReauth, t) {
|
|
|
3509
3804
|
</div>`;
|
|
3510
3805
|
}
|
|
3511
3806
|
function renderAdvancedEditor(state, t) {
|
|
3512
|
-
const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, saveButtonEnabled } = state;
|
|
3513
|
-
const treeHtml = e2eTree.length ? renderTree(e2eTree, selectedFile) : `<div class="tree-item" style="color:#6c7a99">${t("ADVANCED_EDITOR.NO_FILES")}</div>`;
|
|
3807
|
+
const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, testNotes, saveButtonEnabled, isCreatingFile, collapsedDirs, sidebarWidth } = state;
|
|
3808
|
+
const treeHtml = e2eTree.length ? renderTree(e2eTree, selectedFile, collapsedDirs) : `<div class="tree-item" style="color:#6c7a99">${t("ADVANCED_EDITOR.NO_FILES")}</div>`;
|
|
3514
3809
|
const contentHtml = selectedFileContent ? `<div class="file-name">\u{1F4C4} ${escHtml(selectedFile?.name ?? "")}</div>
|
|
3515
|
-
<pre>${
|
|
3810
|
+
<pre class="pre-file">${syntaxHighlight(selectedFileContent.slice(0, 6e3))}${selectedFileContent.length > 6e3 ? "\n..." : ""}</pre>` : `<div class="placeholder">${t("ADVANCED_EDITOR.SELECT_FILE")}</div>`;
|
|
3811
|
+
const notesHtml = testItBlock && testNotes ? `<p class="test-notes">${escHtml(testNotes)}</p>` : "";
|
|
3516
3812
|
const itHtml = testItBlock ? `<div style="margin-top:10px">
|
|
3517
3813
|
<div class="file-name block-header">
|
|
3518
3814
|
<span>${t("ADVANCED_EDITOR.IT_LABEL")}</span>
|
|
3519
3815
|
<button id="btn-copy-it" class="btn-copy">${t("ADVANCED_EDITOR.COPY_IT_BTN")}</button>
|
|
3520
3816
|
</div>
|
|
3521
|
-
<pre
|
|
3817
|
+
<pre class="pre-block">${syntaxHighlight(testItBlock.slice(0, 3e3))}</pre>
|
|
3522
3818
|
</div>` : "";
|
|
3523
3819
|
const interceptorsHtml = interceptorsBlock ? `<div style="margin-top:10px">
|
|
3524
3820
|
<div class="file-name block-header">
|
|
3525
3821
|
<span>${t("ADVANCED_EDITOR.BEFORE_EACH_LABEL")}</span>
|
|
3526
3822
|
<button id="btn-copy-interceptors" class="btn-copy">${t("ADVANCED_EDITOR.COPY_ICP_BTN")}</button>
|
|
3527
3823
|
</div>
|
|
3528
|
-
<pre
|
|
3824
|
+
<pre class="pre-block pre-icp">${syntaxHighlight(interceptorsBlock.slice(0, 3e3))}</pre>
|
|
3529
3825
|
</div>` : "";
|
|
3826
|
+
const newFileForm = isCreatingFile ? `<div class="new-file-form">
|
|
3827
|
+
<input id="input-new-file" type="text" placeholder="${escHtml(t("ADVANCED_EDITOR.NEW_FILE_PLACEHOLDER"))}" autocomplete="off" />
|
|
3828
|
+
<span class="ext">.cy.ts</span>
|
|
3829
|
+
<div class="new-file-actions">
|
|
3830
|
+
<button id="btn-new-file-confirm" class="btn-confirm">${t("ADVANCED_EDITOR.NEW_FILE_CONFIRM")}</button>
|
|
3831
|
+
<button id="btn-new-file-cancel" class="btn-cancel-form">${t("ADVANCED_EDITOR.NEW_FILE_CANCEL")}</button>
|
|
3832
|
+
</div>
|
|
3833
|
+
</div>` : "";
|
|
3834
|
+
const toolbar = `
|
|
3835
|
+
<div class="sidebar-toolbar">
|
|
3836
|
+
<button id="btn-new-file" class="btn-toolbar btn-new">${t("ADVANCED_EDITOR.NEW_FILE_BTN")}</button>
|
|
3837
|
+
<button id="btn-refresh" class="btn-toolbar">${t("ADVANCED_EDITOR.REFRESH_BTN")}</button>
|
|
3838
|
+
</div>`;
|
|
3530
3839
|
return `
|
|
3531
3840
|
<div class="layout">
|
|
3532
|
-
<div class="sidebar"
|
|
3841
|
+
<div class="sidebar" style="width:${sidebarWidth}px">
|
|
3842
|
+
${toolbar}
|
|
3843
|
+
${newFileForm}
|
|
3844
|
+
<div class="tree-scroll">${treeHtml}</div>
|
|
3845
|
+
</div>
|
|
3846
|
+
<div id="resize-handle" class="resize-handle"></div>
|
|
3533
3847
|
<div class="main">
|
|
3534
|
-
<div class="content-area">${contentHtml}${itHtml}${interceptorsHtml}</div>
|
|
3848
|
+
<div class="content-area">${contentHtml}${notesHtml}${itHtml}${interceptorsHtml}</div>
|
|
3535
3849
|
<div class="footer">
|
|
3536
3850
|
<button id="btn-save" class="btn-save"
|
|
3537
3851
|
${!saveButtonEnabled || !testItBlock ? "disabled" : ""}>
|
|
@@ -3545,16 +3859,24 @@ function renderAdvancedEditor(state, t) {
|
|
|
3545
3859
|
</div>
|
|
3546
3860
|
</div>`;
|
|
3547
3861
|
}
|
|
3548
|
-
function renderTree(nodes, selected, indent = 0) {
|
|
3862
|
+
function renderTree(nodes, selected, collapsedDirs, indent = 0, parentPath = "") {
|
|
3549
3863
|
return nodes.map((n) => {
|
|
3864
|
+
const currentPath = parentPath ? `${parentPath}/${n.name}` : n.name;
|
|
3550
3865
|
const isFile = n.kind === "file";
|
|
3551
|
-
const
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3866
|
+
const pad = `padding-left:${6 + indent * 14}px`;
|
|
3867
|
+
if (!isFile) {
|
|
3868
|
+
const dir = n;
|
|
3869
|
+
const hasChildren = (dir.children?.length ?? 0) > 0;
|
|
3870
|
+
const isCollapsed = collapsedDirs.has(currentPath);
|
|
3871
|
+
const arrow = hasChildren ? isCollapsed ? "\u25B6" : "\u25BC" : "\xB7";
|
|
3872
|
+
const dirHtml = `<div class="tree-item dir" style="${pad}" data-dir-path="${escAttr(currentPath)}">
|
|
3873
|
+
<span class="dir-arrow">${arrow}</span>\u{1F4C1} ${escHtml(n.name)}
|
|
3874
|
+
</div>`;
|
|
3875
|
+
if (!hasChildren || isCollapsed) return dirHtml;
|
|
3876
|
+
return dirHtml + renderTree(dir.children, selected, collapsedDirs, indent + 1, currentPath);
|
|
3557
3877
|
}
|
|
3878
|
+
const isSel = selected?.name === n.name;
|
|
3879
|
+
const cls = `tree-item${isSel ? " selected" : ""}`;
|
|
3558
3880
|
const data = JSON.stringify({ kind: n.kind, name: n.name }).replace(/"/g, """);
|
|
3559
3881
|
return `<div class="${cls}" style="${pad}" data-file="${data}">\u{1F4C4} ${escHtml(n.name)}</div>`;
|
|
3560
3882
|
}).join("");
|
|
@@ -3584,12 +3906,17 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3584
3906
|
selectedFileContent = null;
|
|
3585
3907
|
testItBlock = "";
|
|
3586
3908
|
interceptorsBlock = "";
|
|
3909
|
+
testNotes = "";
|
|
3587
3910
|
isPreviewMode = false;
|
|
3588
3911
|
previewFileName = null;
|
|
3589
3912
|
previewFileContent = null;
|
|
3913
|
+
isCreatingFile = false;
|
|
3914
|
+
collapsedDirs = /* @__PURE__ */ new Set();
|
|
3915
|
+
sidebarWidth = 220;
|
|
3590
3916
|
hasPermission = false;
|
|
3591
3917
|
needsReauth = false;
|
|
3592
3918
|
_dirHandle = null;
|
|
3919
|
+
_e2eHandle = null;
|
|
3593
3920
|
constructor() {
|
|
3594
3921
|
super();
|
|
3595
3922
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
@@ -3631,7 +3958,8 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3631
3958
|
try {
|
|
3632
3959
|
for await (const entry of this._dirHandle.values()) {
|
|
3633
3960
|
if (entry.kind === "directory" && entry.name === "e2e") {
|
|
3634
|
-
|
|
3961
|
+
this._e2eHandle = entry;
|
|
3962
|
+
const tree = await this.transformationService.scanDirectory(this._e2eHandle);
|
|
3635
3963
|
this.e2eTree = tree.children ?? [];
|
|
3636
3964
|
this.render();
|
|
3637
3965
|
return;
|
|
@@ -3640,13 +3968,40 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3640
3968
|
} catch {
|
|
3641
3969
|
}
|
|
3642
3970
|
}
|
|
3971
|
+
async createNewFile(rawName) {
|
|
3972
|
+
if (!this._e2eHandle) return;
|
|
3973
|
+
const name = rawName.trim().replace(/\.cy\.ts$/, "");
|
|
3974
|
+
if (!name) return;
|
|
3975
|
+
const fileName = `${name}.cy.ts`;
|
|
3976
|
+
const template = `describe('${name}', () => {
|
|
3977
|
+
|
|
3978
|
+
it('should ', () => {
|
|
3979
|
+
|
|
3980
|
+
});
|
|
3981
|
+
|
|
3982
|
+
});
|
|
3983
|
+
`;
|
|
3984
|
+
try {
|
|
3985
|
+
const fileHandle = await this._e2eHandle.getFileHandle(fileName, { create: true });
|
|
3986
|
+
const writable = await fileHandle.createWritable();
|
|
3987
|
+
await writable.write(template);
|
|
3988
|
+
await writable.close();
|
|
3989
|
+
} catch {
|
|
3990
|
+
}
|
|
3991
|
+
this.isCreatingFile = false;
|
|
3992
|
+
await this.getFoldersData();
|
|
3993
|
+
}
|
|
3994
|
+
async refreshTree() {
|
|
3995
|
+
await this.getFoldersData();
|
|
3996
|
+
}
|
|
3643
3997
|
async saveCommandsToFile() {
|
|
3644
3998
|
if (!this.selectedFileHandle || !this.selectedFileContent || !this.testItBlock) return;
|
|
3645
3999
|
let content = this.selectedFileContent;
|
|
3646
4000
|
if (this.interceptorsBlock) {
|
|
3647
4001
|
content = this.transformationService.insertBeforeEach(content, this.interceptorsBlock);
|
|
3648
4002
|
}
|
|
3649
|
-
|
|
4003
|
+
const comment = this.testNotes ? this.transformationService.buildBlockComment(this.testNotes) + "\n" : "";
|
|
4004
|
+
content = this.transformationService.insertItBlock(content, comment + this.testItBlock);
|
|
3650
4005
|
if (!content) return;
|
|
3651
4006
|
const writable = await this.selectedFileHandle.createWritable();
|
|
3652
4007
|
await writable.write(content);
|
|
@@ -3673,9 +4028,11 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3673
4028
|
if (test) {
|
|
3674
4029
|
this.testItBlock = test.itBlock ?? "";
|
|
3675
4030
|
this.interceptorsBlock = test.interceptorsBlock ?? "";
|
|
4031
|
+
this.testNotes = test.notes ?? "";
|
|
3676
4032
|
} else {
|
|
3677
4033
|
this.testItBlock = "";
|
|
3678
4034
|
this.interceptorsBlock = "";
|
|
4035
|
+
this.testNotes = "";
|
|
3679
4036
|
}
|
|
3680
4037
|
this.render();
|
|
3681
4038
|
}
|
|
@@ -3697,6 +4054,44 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3697
4054
|
composed: true
|
|
3698
4055
|
}));
|
|
3699
4056
|
}
|
|
4057
|
+
toggleDir(path) {
|
|
4058
|
+
if (this.collapsedDirs.has(path)) {
|
|
4059
|
+
this.collapsedDirs.delete(path);
|
|
4060
|
+
} else {
|
|
4061
|
+
this.collapsedDirs.add(path);
|
|
4062
|
+
}
|
|
4063
|
+
this.render();
|
|
4064
|
+
}
|
|
4065
|
+
setupResizeHandle() {
|
|
4066
|
+
const handle = this.shadow.getElementById("resize-handle");
|
|
4067
|
+
const sidebar = this.shadow.querySelector(".sidebar");
|
|
4068
|
+
if (!handle || !sidebar) return;
|
|
4069
|
+
let startX = 0;
|
|
4070
|
+
let startWidth = 0;
|
|
4071
|
+
const onMouseMove = (e) => {
|
|
4072
|
+
const delta = e.clientX - startX;
|
|
4073
|
+
const newWidth = Math.max(140, Math.min(500, startWidth + delta));
|
|
4074
|
+
this.sidebarWidth = newWidth;
|
|
4075
|
+
sidebar.style.width = `${newWidth}px`;
|
|
4076
|
+
};
|
|
4077
|
+
const onMouseUp = () => {
|
|
4078
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
4079
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
4080
|
+
document.body.style.cursor = "";
|
|
4081
|
+
document.body.style.userSelect = "";
|
|
4082
|
+
handle.classList.remove("dragging");
|
|
4083
|
+
};
|
|
4084
|
+
handle.addEventListener("mousedown", (e) => {
|
|
4085
|
+
startX = e.clientX;
|
|
4086
|
+
startWidth = sidebar.offsetWidth;
|
|
4087
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
4088
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
4089
|
+
document.body.style.cursor = "col-resize";
|
|
4090
|
+
document.body.style.userSelect = "none";
|
|
4091
|
+
handle.classList.add("dragging");
|
|
4092
|
+
e.preventDefault();
|
|
4093
|
+
});
|
|
4094
|
+
}
|
|
3700
4095
|
closePreview() {
|
|
3701
4096
|
this.isPreviewMode = false;
|
|
3702
4097
|
this.previewFileName = null;
|
|
@@ -3727,7 +4122,11 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3727
4122
|
selectedFileContent: this.selectedFileContent,
|
|
3728
4123
|
testItBlock: this.testItBlock,
|
|
3729
4124
|
interceptorsBlock: this.interceptorsBlock,
|
|
3730
|
-
|
|
4125
|
+
testNotes: this.testNotes,
|
|
4126
|
+
saveButtonEnabled: this.saveButtonEnabled,
|
|
4127
|
+
isCreatingFile: this.isCreatingFile,
|
|
4128
|
+
collapsedDirs: this.collapsedDirs,
|
|
4129
|
+
sidebarWidth: this.sidebarWidth
|
|
3731
4130
|
}, this.t.bind(this))}`;
|
|
3732
4131
|
this.shadow.querySelectorAll("[data-file]").forEach((el) => {
|
|
3733
4132
|
el.addEventListener("click", () => {
|
|
@@ -3735,11 +4134,41 @@ var AdvancedTestEditorElement = class extends HTMLElement {
|
|
|
3735
4134
|
if (data) this.onFileClick(JSON.parse(data));
|
|
3736
4135
|
});
|
|
3737
4136
|
});
|
|
4137
|
+
this.shadow.querySelectorAll("[data-dir-path]").forEach((el) => {
|
|
4138
|
+
el.addEventListener("click", () => {
|
|
4139
|
+
const path = el.dataset["dirPath"];
|
|
4140
|
+
if (path) this.toggleDir(path);
|
|
4141
|
+
});
|
|
4142
|
+
});
|
|
4143
|
+
this.setupResizeHandle();
|
|
3738
4144
|
this.shadow.getElementById("btn-save")?.addEventListener("click", () => this.saveCommandsToFile());
|
|
3739
4145
|
this.shadow.getElementById("btn-edit")?.addEventListener("click", () => this.openEditManually());
|
|
3740
4146
|
this.shadow.getElementById("btn-copy-it")?.addEventListener("click", () => this.copyToClipboard(this.testItBlock));
|
|
3741
4147
|
this.shadow.getElementById("btn-copy-interceptors")?.addEventListener("click", () => this.copyToClipboard(this.interceptorsBlock));
|
|
3742
4148
|
this.shadow.getElementById("btn-close")?.addEventListener("click", () => this.closePreview());
|
|
4149
|
+
this.shadow.getElementById("btn-new-file")?.addEventListener("click", () => {
|
|
4150
|
+
this.isCreatingFile = !this.isCreatingFile;
|
|
4151
|
+
this.render();
|
|
4152
|
+
if (this.isCreatingFile) this.shadow.getElementById("input-new-file")?.focus();
|
|
4153
|
+
});
|
|
4154
|
+
this.shadow.getElementById("btn-refresh")?.addEventListener("click", () => this.refreshTree());
|
|
4155
|
+
this.shadow.getElementById("btn-new-file-confirm")?.addEventListener("click", () => {
|
|
4156
|
+
const input2 = this.shadow.getElementById("input-new-file");
|
|
4157
|
+
this.createNewFile(input2?.value ?? "");
|
|
4158
|
+
});
|
|
4159
|
+
this.shadow.getElementById("btn-new-file-cancel")?.addEventListener("click", () => {
|
|
4160
|
+
this.isCreatingFile = false;
|
|
4161
|
+
this.render();
|
|
4162
|
+
});
|
|
4163
|
+
const input = this.shadow.getElementById("input-new-file");
|
|
4164
|
+
input?.addEventListener("keydown", (e) => {
|
|
4165
|
+
if (e.key === "Enter") {
|
|
4166
|
+
this.createNewFile(input.value);
|
|
4167
|
+
} else if (e.key === "Escape") {
|
|
4168
|
+
this.isCreatingFile = false;
|
|
4169
|
+
this.render();
|
|
4170
|
+
}
|
|
4171
|
+
});
|
|
3743
4172
|
}
|
|
3744
4173
|
};
|
|
3745
4174
|
if (!customElements.get("advanced-test-editor")) {
|
|
@@ -4247,6 +4676,7 @@ function renderRecorderWidget(rec, paused, t) {
|
|
|
4247
4676
|
// src/components/lib-e2e-recorder/lib-e2e-recorder.ts
|
|
4248
4677
|
var LibE2eRecorderElement = class extends HTMLElement {
|
|
4249
4678
|
shadow;
|
|
4679
|
+
_isDisabled = false;
|
|
4250
4680
|
keydownHandler;
|
|
4251
4681
|
recordingUnsub;
|
|
4252
4682
|
commandsUnsub;
|
|
@@ -4260,6 +4690,7 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4260
4690
|
recording;
|
|
4261
4691
|
persistence;
|
|
4262
4692
|
translation;
|
|
4693
|
+
isVisible = false;
|
|
4263
4694
|
isRecording = false;
|
|
4264
4695
|
isPaused = false;
|
|
4265
4696
|
cypressCommands = [];
|
|
@@ -4274,6 +4705,10 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4274
4705
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
4275
4706
|
}
|
|
4276
4707
|
connectedCallback() {
|
|
4708
|
+
if ("Cypress" in window) {
|
|
4709
|
+
this._isDisabled = true;
|
|
4710
|
+
return;
|
|
4711
|
+
}
|
|
4277
4712
|
if (!this.getAttribute("data-cy")) {
|
|
4278
4713
|
this.setAttribute("data-cy", "lib-e2e-cypress-for-dummys");
|
|
4279
4714
|
}
|
|
@@ -4290,10 +4725,12 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4290
4725
|
this.initSelectorStrategy();
|
|
4291
4726
|
this.initSubscriptions();
|
|
4292
4727
|
this.render();
|
|
4728
|
+
this.initVisibility();
|
|
4293
4729
|
this.keydownHandler = (e) => this.handleKeyboardEvent(e);
|
|
4294
4730
|
window.addEventListener("keydown", this.keydownHandler);
|
|
4295
4731
|
}
|
|
4296
4732
|
disconnectedCallback() {
|
|
4733
|
+
if (this._isDisabled) return;
|
|
4297
4734
|
window.removeEventListener("keydown", this.keydownHandler);
|
|
4298
4735
|
this.recordingUnsub?.();
|
|
4299
4736
|
this.commandsUnsub?.();
|
|
@@ -4354,6 +4791,16 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4354
4791
|
document.body.appendChild(picker);
|
|
4355
4792
|
});
|
|
4356
4793
|
}
|
|
4794
|
+
async initVisibility() {
|
|
4795
|
+
if (this.hasAttribute("start-hidden")) {
|
|
4796
|
+
this.isVisible = this.getAttribute("start-hidden") === "false";
|
|
4797
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4798
|
+
return;
|
|
4799
|
+
}
|
|
4800
|
+
const config = await this.persistence.getGeneralConfig();
|
|
4801
|
+
this.isVisible = config?.["startHidden"] !== "true";
|
|
4802
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4803
|
+
}
|
|
4357
4804
|
async initSelectorStrategy() {
|
|
4358
4805
|
const config = await this.persistence.getGeneralConfig();
|
|
4359
4806
|
const strategy = config?.["selectorStrategy"];
|
|
@@ -4373,6 +4820,12 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4373
4820
|
handleKeyboardEvent(event) {
|
|
4374
4821
|
if (!event.ctrlKey) return;
|
|
4375
4822
|
const key = event.key.toLowerCase();
|
|
4823
|
+
if (key === "e" && event.shiftKey) {
|
|
4824
|
+
event.preventDefault();
|
|
4825
|
+
this.toggleVisibility();
|
|
4826
|
+
return;
|
|
4827
|
+
}
|
|
4828
|
+
if (!this.isVisible) return;
|
|
4376
4829
|
if (key === "r") {
|
|
4377
4830
|
event.preventDefault();
|
|
4378
4831
|
this.toggle();
|
|
@@ -4390,6 +4843,10 @@ var LibE2eRecorderElement = class extends HTMLElement {
|
|
|
4390
4843
|
this.showSettingsDialog();
|
|
4391
4844
|
}
|
|
4392
4845
|
}
|
|
4846
|
+
toggleVisibility() {
|
|
4847
|
+
this.isVisible = !this.isVisible;
|
|
4848
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4849
|
+
}
|
|
4393
4850
|
// ── recording history (task 5) ────────────────────────────────────────────
|
|
4394
4851
|
saveRecordingHistory() {
|
|
4395
4852
|
if (!this.cypressCommands.length) return;
|
|
@@ -4625,13 +5082,13 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4625
5082
|
child.translation = this.translation;
|
|
4626
5083
|
container.appendChild(child);
|
|
4627
5084
|
child.addEventListener("savetest", (e) => {
|
|
4628
|
-
const { description, tags } = e.detail ?? {};
|
|
4629
|
-
this.onSaveTest(description ?? null, tags ?? []);
|
|
5085
|
+
const { description, notes, tags } = e.detail ?? {};
|
|
5086
|
+
this.onSaveTest(description ?? null, tags ?? [], notes ?? "");
|
|
4630
5087
|
import_sweetalert2.default.close();
|
|
4631
5088
|
});
|
|
4632
5089
|
child.addEventListener("saveandexport", (e) => {
|
|
4633
|
-
const { description, tags } = e.detail ?? {};
|
|
4634
|
-
this.onSaveAndExportTest(description ?? null, tags ?? []);
|
|
5090
|
+
const { description, notes, tags } = e.detail ?? {};
|
|
5091
|
+
this.onSaveAndExportTest(description ?? null, tags ?? [], notes ?? "");
|
|
4635
5092
|
import_sweetalert2.default.close();
|
|
4636
5093
|
});
|
|
4637
5094
|
},
|
|
@@ -4662,6 +5119,10 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4662
5119
|
child.addEventListener("smartselectorchange", (e) => {
|
|
4663
5120
|
this.smartSelectorEnabled = e.detail;
|
|
4664
5121
|
});
|
|
5122
|
+
child.addEventListener("starthiddenchange", (e) => {
|
|
5123
|
+
this.isVisible = !e.detail;
|
|
5124
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
5125
|
+
});
|
|
4665
5126
|
},
|
|
4666
5127
|
willClose: () => {
|
|
4667
5128
|
this.isSettingsDialogOpen = false;
|
|
@@ -4674,7 +5135,7 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4674
5135
|
this.toggleModal("isAdvancedEditorDialogOpen", () => {
|
|
4675
5136
|
import_sweetalert2.default.fire({
|
|
4676
5137
|
title: this.translation.translate("MAIN_FRAME.SHOW_ADVANCED_EDITOR"),
|
|
4677
|
-
html: '<div id="advanced-editor-modal-content" style="min-height:
|
|
5138
|
+
html: '<div id="advanced-editor-modal-content" style="flex:1;min-height:0;display:flex;flex-direction:column;padding:0"></div>',
|
|
4678
5139
|
showCloseButton: true,
|
|
4679
5140
|
showConfirmButton: false,
|
|
4680
5141
|
allowOutsideClick: false,
|
|
@@ -4683,6 +5144,20 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4683
5144
|
didOpen: () => {
|
|
4684
5145
|
makeSwalDraggable();
|
|
4685
5146
|
setSwal2DataCyAttribute();
|
|
5147
|
+
const popup = import_sweetalert2.default.getPopup();
|
|
5148
|
+
if (popup) {
|
|
5149
|
+
popup.style.height = "600px";
|
|
5150
|
+
const htmlContainer = popup.querySelector(".swal2-html-container");
|
|
5151
|
+
if (htmlContainer) {
|
|
5152
|
+
htmlContainer.style.flex = "1";
|
|
5153
|
+
htmlContainer.style.minHeight = "0";
|
|
5154
|
+
htmlContainer.style.overflow = "hidden";
|
|
5155
|
+
htmlContainer.style.padding = "0";
|
|
5156
|
+
htmlContainer.style.margin = "0";
|
|
5157
|
+
htmlContainer.style.display = "flex";
|
|
5158
|
+
htmlContainer.style.flexDirection = "column";
|
|
5159
|
+
}
|
|
5160
|
+
}
|
|
4686
5161
|
const container = document.getElementById("advanced-editor-modal-content");
|
|
4687
5162
|
if (!container) return;
|
|
4688
5163
|
const child = document.createElement("advanced-test-editor");
|
|
@@ -4710,7 +5185,10 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4710
5185
|
this.isAdvancedEditorDialogOpen = false;
|
|
4711
5186
|
}
|
|
4712
5187
|
});
|
|
4713
|
-
|
|
5188
|
+
setTimeout(() => {
|
|
5189
|
+
const popup = import_sweetalert2.default.getPopup();
|
|
5190
|
+
if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 0 });
|
|
5191
|
+
}, 0);
|
|
4714
5192
|
});
|
|
4715
5193
|
}
|
|
4716
5194
|
showFileEditorDialog(handle, content, fileName, testId, itBlock = "", interceptorsBlock = "") {
|
|
@@ -4756,18 +5234,18 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4756
5234
|
this.resizePopup();
|
|
4757
5235
|
}
|
|
4758
5236
|
// ── save handlers ─────────────────────────────────────────────────────────
|
|
4759
|
-
async onSaveTest(description, tags = []) {
|
|
5237
|
+
async onSaveTest(description, tags = [], notes = "") {
|
|
4760
5238
|
if (description) {
|
|
4761
|
-
await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags);
|
|
5239
|
+
await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);
|
|
4762
5240
|
this.recording.clearCommands();
|
|
4763
5241
|
this.clearRecordingHistory();
|
|
4764
5242
|
this.cypressCommands = [];
|
|
4765
5243
|
this.interceptors = [];
|
|
4766
5244
|
}
|
|
4767
5245
|
}
|
|
4768
|
-
async onSaveAndExportTest(description, tags = []) {
|
|
5246
|
+
async onSaveAndExportTest(description, tags = [], notes = "") {
|
|
4769
5247
|
if (description) {
|
|
4770
|
-
const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags);
|
|
5248
|
+
const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);
|
|
4771
5249
|
this.recording.clearCommands();
|
|
4772
5250
|
this.clearRecordingHistory();
|
|
4773
5251
|
this.cypressCommands = [];
|
|
@@ -4794,6 +5272,7 @@ cypress/ <span style="color:#484f58">${this.translation.translate("RECOR
|
|
|
4794
5272
|
render() {
|
|
4795
5273
|
const rec = this.isRecording;
|
|
4796
5274
|
const paused = this.isPaused;
|
|
5275
|
+
this.style.display = this.isVisible ? "" : "none";
|
|
4797
5276
|
this.shadow.innerHTML = `<style>${getRecorderStyles(rec, paused)}</style>${renderRecorderWidget(rec, paused, this.translation.translate.bind(this.translation))}`;
|
|
4798
5277
|
this.shadow.querySelector('[data-action="toggle"]')?.addEventListener("click", () => this.toggle());
|
|
4799
5278
|
this.shadow.querySelector('[data-action="pause"]')?.addEventListener("click", () => this.togglePause());
|