lib-e2e-cypress-for-dummys-ts 0.5.0 β 0.6.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 +20 -0
- package/dist/index.cjs +214 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -2
- package/dist/index.d.ts +51 -2
- package/dist/index.js +207 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/selector-quality.utils.ts","../src/components/selector-picker/selector-picker.styles.ts","../src/utils/html.utils.ts","../src/components/selector-picker/selector-picker.template.ts","../src/components/selector-picker/selector-picker.ts","../src/index.ts","../src/models/lang.model.ts","../src/models/input-types.model.ts","../src/models/db-schema.model.ts","../src/models/active-session.model.ts","../src/utils/subject.ts","../src/i18n/es.ts","../src/i18n/en.ts","../src/i18n/fr.ts","../src/i18n/it.ts","../src/i18n/de.ts","../src/services/translation.service.ts","../src/utils/code-format.utils.ts","../src/services/transformation.service.ts","../src/services/advanced-test.transformation.service.ts","../src/services/recording.service.ts","../src/services/persistence.service.ts","../src/services/http-monitor.ts","../src/utils/styles.utils.ts","../src/utils/modal.utils.ts","../src/utils/toast.utils.ts","../src/utils/export-selection.utils.ts","../src/utils/host.utils.ts","../src/components/test-previsualizer/test-previsualizer.styles.ts","../src/components/test-previsualizer/test-previsualizer.template.ts","../src/components/test-previsualizer/test-previsualizer.ts","../src/components/save-test/save-test.styles.ts","../src/components/save-test/save-test.template.ts","../src/components/save-test/save-test.ts","../src/components/test-editor/test-editor.styles.ts","../src/components/test-editor/test-editor.template.ts","../src/utils/syntax-highlight.utils.ts","../src/components/test-editor/test-editor.ts","../src/components/configuration/configuration.styles.ts","../src/components/configuration/configuration.template.ts","../src/components/configuration/configuration.ts","../src/components/advanced-test-editor/advanced-test-editor.styles.ts","../src/components/advanced-test-editor/advanced-test-editor.template.ts","../src/components/advanced-test-editor/advanced-test-editor.ts","../src/components/file-preview/file-preview.styles.ts","../src/components/file-preview/file-preview.template.ts","../src/components/file-preview/file-preview.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.styles.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.template.ts"],"sourcesContent":["export type SelectorQuality = 'excellent' | 'good' | 'acceptable' | 'poor';\n\nexport const FORBIDDEN_ID_PREFIXES = [\n 'cdk-', 'mat-', 'p-', 'ng-', 'mdc-',\n 'primeng-', 'auto-', 'field-', 'input-', 'select-',\n];\n\nexport function getSelectorQuality(el: HTMLElement): SelectorQuality {\n if (\n el.hasAttribute('data-cy') ||\n el.hasAttribute('data-testid') ||\n el.hasAttribute('aria-label')\n ) {\n return 'excellent';\n }\n\n const rawId = el.id;\n if (\n rawId &&\n rawId.length < 25 &&\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\n !/^\\d+$/.test(rawId)\n ) {\n return 'good';\n }\n\n if (typeof el.className === 'string' && el.className.trim().length > 0) {\n return 'acceptable';\n }\n\n return 'poor';\n}\n\n/** Returns the best cy.get() selector string for a given element. */\nexport function buildPickerSelector(el: HTMLElement): string {\n const dataCy = el.getAttribute('data-cy');\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\n\n const dataTestid = el.getAttribute('data-testid');\n if (dataTestid) return `[data-testid=\"${dataTestid}\"]`;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\n\n const rawId = el.id;\n if (\n rawId &&\n rawId.length < 25 &&\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\n !/^\\d+$/.test(rawId)\n ) {\n return `#${rawId}`;\n }\n\n if (typeof el.className === 'string' && el.className.trim().length > 0) {\n const classes = el.className.trim().split(/\\s+/);\n return classes.map((c) => `.${c}`).join('');\n }\n\n return el.tagName.toLowerCase();\n}\n\n/** Human-readable key attribute/selector preview for a picker row (raw, unescaped). */\nexport function keyAttrDisplay(el: HTMLElement): string {\n for (const attr of ['data-cy', 'data-testid', 'aria-label']) {\n const v = el.getAttribute(attr);\n if (v) return `${attr}=\"${v}\"`;\n }\n if (el.id) return `id=\"${el.id}\"`;\n if (el.className && el.className.trim()) {\n return el.className.trim().split(/\\s+/).map((c) => `.${c}`).join('');\n }\n return '';\n}\n\n/** Plain, serializable view-model for one picker row β no DOM held. */\nexport interface PickerRow {\n quality: SelectorQuality;\n selector: string;\n tag: string;\n attr: string;\n}\n\n/** Reads an element once and returns the plain data a picker row needs to render. */\nexport function describePickerRow(el: HTMLElement): PickerRow {\n return {\n quality: getSelectorQuality(el),\n selector: buildPickerSelector(el),\n tag: el.tagName.toLowerCase(),\n attr: keyAttrDisplay(el),\n };\n}\n","export const SELECTOR_PICKER_STYLES = `\r\n :host {\r\n position: fixed;\r\n z-index: 2147483647;\r\n top: 0;\r\n left: 0;\r\n width: 100vw;\r\n height: 100vh;\r\n pointer-events: none;\r\n }\r\n\r\n .overlay {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n pointer-events: all;\r\n background: #161b22;\r\n border: 1px solid #30363d;\r\n border-radius: 10px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.6);\r\n min-width: 420px;\r\n max-width: 600px;\r\n font-family: 'Segoe UI', system-ui, sans-serif;\r\n color: #e6edf3;\r\n font-size: 13px;\r\n }\r\n\r\n .header {\r\n padding: 12px 16px 8px;\r\n border-bottom: 1px solid #21262d;\r\n font-weight: 600;\r\n font-size: 13px;\r\n color: #8b949e;\r\n letter-spacing: 0.04em;\r\n text-transform: uppercase;\r\n }\r\n\r\n .list {\r\n max-height: 320px;\r\n overflow-y: auto;\r\n padding: 6px 0;\r\n }\r\n\r\n .row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 7px 14px;\r\n cursor: pointer;\r\n border-radius: 6px;\r\n margin: 1px 6px;\r\n transition: background 0.1s;\r\n }\r\n\r\n .row:hover,\r\n .row.selected {\r\n background: #21262d;\r\n }\r\n\r\n .row.selected {\r\n outline: 2px solid #388bfd;\r\n outline-offset: -2px;\r\n }\r\n\r\n .quality-badge {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: 50%;\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 10px;\r\n }\r\n\r\n .badge-excellent { background: #238636; }\r\n .badge-good { background: #1f6feb; }\r\n .badge-acceptable{ background: #9e6a03; }\r\n .badge-poor { background: #da3633; }\r\n\r\n .tag-name {\r\n font-family: monospace;\r\n font-size: 12px;\r\n color: #8b949e;\r\n flex-shrink: 0;\r\n }\r\n\r\n .attr-value {\r\n font-family: monospace;\r\n font-size: 12px;\r\n color: #c9d1d9;\r\n flex: 1;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .selector-preview {\r\n font-family: monospace;\r\n font-size: 11px;\r\n color: #58a6ff;\r\n flex-shrink: 0;\r\n max-width: 180px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .poor-warning {\r\n font-size: 10px;\r\n color: #f85149;\r\n margin-left: auto;\r\n }\r\n\r\n .footer {\r\n padding: 8px 14px 10px;\r\n border-top: 1px solid #21262d;\r\n display: flex;\r\n gap: 16px;\r\n font-size: 11px;\r\n color: #484f58;\r\n }\r\n\r\n .hint kbd {\r\n background: #21262d;\r\n border: 1px solid #30363d;\r\n border-radius: 3px;\r\n padding: 1px 5px;\r\n font-size: 10px;\r\n color: #8b949e;\r\n }\r\n`;\r\n","export function escHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nexport function escAttr(s: string): string {\n return s.replace(/\"/g, '"').replace(/</g, '<');\n}\n","import type { PickerRow, SelectorQuality } from '../../utils/selector-quality.utils';\r\nimport { escHtml } from '../../utils/html.utils';\r\n\r\nconst QUALITY_EMOJI: Record<SelectorQuality, string> = {\r\n excellent: 'π’',\r\n good: 'π΅',\r\n acceptable: 'π‘',\r\n poor: 'π΄',\r\n};\r\n\r\nconst QUALITY_CLASS: Record<SelectorQuality, string> = {\r\n excellent: 'badge-excellent',\r\n good: 'badge-good',\r\n acceptable: 'badge-acceptable',\r\n poor: 'badge-poor',\r\n};\r\n\r\nexport function renderPickerRows(\r\n rows: PickerRow[],\r\n selectedIndex: number,\r\n t: (key: string) => string,\r\n): string {\r\n return rows.map((row, i) => {\r\n const isSelected = i === selectedIndex;\r\n const isPoor = row.quality === 'poor';\r\n\r\n return `\r\n <div class=\"row${isSelected ? ' selected' : ''}\" data-idx=\"${i}\" role=\"option\" aria-selected=\"${isSelected}\">\r\n <span class=\"quality-badge ${QUALITY_CLASS[row.quality]}\" title=\"${escHtml(t(`SELECTOR_PICKER.QUALITY_${row.quality.toUpperCase()}`))}\">\r\n ${QUALITY_EMOJI[row.quality]}\r\n </span>\r\n <span class=\"tag-name\"><${escHtml(row.tag)}></span>\r\n ${row.attr ? `<span class=\"attr-value\">${escHtml(row.attr)}</span>` : '<span class=\"attr-value\"></span>'}\r\n <span class=\"selector-preview\">${escHtml(row.selector)}</span>\r\n ${isPoor ? `<span class=\"poor-warning\" title=\"${escHtml(t('SELECTOR_PICKER.QUALITY_POOR'))}\">β </span>` : ''}\r\n </div>`;\r\n }).join('');\r\n}\r\n\r\nexport function renderPicker(\r\n rows: PickerRow[],\r\n selectedIndex: number,\r\n t: (key: string) => string,\r\n): string {\r\n return `\r\n <div class=\"overlay\" role=\"listbox\">\r\n <div class=\"header\">${escHtml(t('SELECTOR_PICKER.TITLE'))}</div>\r\n <div class=\"list\">\r\n ${renderPickerRows(rows, selectedIndex, t)}\r\n </div>\r\n <div class=\"footer\">\r\n <span class=\"hint\"><kbd>ββ</kbd> ${escHtml(t('SELECTOR_PICKER.PREVIEW_LABEL'))}</span>\r\n <span class=\"hint\"><kbd>Enter</kbd> ${escHtml(t('SELECTOR_PICKER.CONFIRM_HINT'))}</span>\r\n <span class=\"hint\"><kbd>Esc</kbd> ${escHtml(t('SELECTOR_PICKER.CANCEL_HINT'))}</span>\r\n </div>\r\n </div>`;\r\n}\r\n","import type { RecordingService } from '../../services/recording.service';\r\nimport type { TranslationService } from '../../services/translation.service';\r\nimport { describePickerRow, type PickerRow } from '../../utils/selector-quality.utils';\r\nimport { SELECTOR_PICKER_STYLES } from './selector-picker.styles';\r\nimport { renderPicker } from './selector-picker.template';\r\n\r\nconst OWN_DATA_CY = 'lib-e2e-cypress-for-dummys';\r\nconst MAX_ANCESTORS = 10;\r\n\r\nexport class SelectorPickerElement extends HTMLElement {\r\n targetElement: HTMLElement | null = null;\r\n recording!: RecordingService;\r\n translation!: TranslationService;\r\n\r\n private shadow: ShadowRoot;\r\n private ancestors: HTMLElement[] = [];\r\n private rows: PickerRow[] = [];\r\n private selectedIndex = 0;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private unsubRecording: (() => void) | null = null;\r\n private unsubPause: (() => void) | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n this.setAttribute('data-cy', 'lib-e2e-cypress-for-dummys');\r\n this.ancestors = this.buildAncestors();\r\n this.rows = this.ancestors.map(describePickerRow);\r\n this.selectedIndex = this.findBestIndex();\r\n this.render();\r\n this.attachKeyListener();\r\n this.attachRowClickListeners();\r\n this.subscribeToRecordingChanges();\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.detachKeyListener();\r\n this.unsubRecording?.();\r\n this.unsubPause?.();\r\n }\r\n\r\n private t(key: string): string {\r\n return this.translation?.translate(key) ?? key;\r\n }\r\n\r\n // ββ Ancestor chain ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private buildAncestors(): HTMLElement[] {\r\n const chain: HTMLElement[] = [];\r\n let current: HTMLElement | null = this.targetElement;\r\n\r\n while (current && current.tagName.toLowerCase() !== 'html' && chain.length < MAX_ANCESTORS) {\r\n if (current.getAttribute('data-cy') === OWN_DATA_CY) {\r\n current = current.parentElement;\r\n continue;\r\n }\r\n chain.push(current);\r\n current = current.parentElement;\r\n }\r\n\r\n return chain;\r\n }\r\n\r\n private findBestIndex(): number {\r\n for (let i = 0; i < this.rows.length; i++) {\r\n const q = this.rows[i].quality;\r\n if (q === 'excellent' || q === 'good' || q === 'acceptable') return i;\r\n }\r\n return 0;\r\n }\r\n\r\n // ββ Rendering βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${SELECTOR_PICKER_STYLES}</style>${renderPicker(\r\n this.rows,\r\n this.selectedIndex,\r\n this.t.bind(this),\r\n )}`;\r\n }\r\n\r\n // ββ Keyboard ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private attachKeyListener(): void {\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if (e.key === 'ArrowDown') {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.selectedIndex = (this.selectedIndex + 1) % this.ancestors.length;\r\n this.render();\r\n this.attachRowClickListeners();\r\n } else if (e.key === 'ArrowUp') {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.selectedIndex = (this.selectedIndex - 1 + this.ancestors.length) % this.ancestors.length;\r\n this.render();\r\n this.attachRowClickListeners();\r\n } else if (e.key === 'Enter') {\r\n e.stopPropagation();\r\n this.confirm(this.selectedIndex);\r\n } else if (e.key === 'Escape') {\r\n e.stopPropagation();\r\n this.cancel();\r\n }\r\n };\r\n window.addEventListener('keydown', this.keyHandler, { capture: true });\r\n }\r\n\r\n private detachKeyListener(): void {\r\n if (this.keyHandler) {\r\n window.removeEventListener('keydown', this.keyHandler, { capture: true });\r\n this.keyHandler = null;\r\n }\r\n }\r\n\r\n // ββ Row click listeners βββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private attachRowClickListeners(): void {\r\n this.shadow.querySelectorAll('[data-idx]').forEach((row) => {\r\n (row as HTMLElement).addEventListener('click', () => {\r\n const idx = parseInt((row as HTMLElement).dataset['idx'] ?? '0', 10);\r\n this.confirm(idx);\r\n });\r\n });\r\n }\r\n\r\n // ββ Recording auto-close ββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private subscribeToRecordingChanges(): void {\r\n this.unsubRecording = this.recording.onRecordingChange((isRecording) => {\r\n if (!isRecording) this.closeSilently();\r\n });\r\n this.unsubPause = this.recording.onPauseChange((isPaused) => {\r\n if (isPaused) this.closeSilently();\r\n });\r\n }\r\n\r\n // ββ Actions βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private confirm(index: number): void {\r\n const row = this.rows[index];\r\n if (!row) return;\r\n const command = `cy.get('${row.selector}').click()`;\r\n this.recording.appendCommand(command);\r\n this.dispatchEvent(new CustomEvent('selectorchosen', { detail: command, bubbles: true, composed: true }));\r\n this.closeSilently();\r\n }\r\n\r\n private cancel(): void {\r\n this.dispatchEvent(new CustomEvent('pickercancelled', { bubbles: true, composed: true }));\r\n this.closeSilently();\r\n }\r\n\r\n private closeSilently(): void {\r\n this.detachKeyListener();\r\n this.unsubRecording?.();\r\n this.unsubPause?.();\r\n this.unsubRecording = null;\r\n this.unsubPause = null;\r\n this.remove();\r\n }\r\n}\r\n\r\nif (!customElements.get('selector-picker')) {\r\n customElements.define('selector-picker', SelectorPickerElement);\r\n}\r\n","// Public API β populated as migration phases are completed\r\n// Keep in sync with package.json \"version\" (asserted in specs/public-api.spec.ts).\r\nexport const VERSION = '0.5.0';\r\n\r\n// Phase 1 β Models\r\nexport * from './models/lang.model';\r\nexport * from './models/input-types.model';\r\nexport * from './models/db-schema.model';\r\nexport * from './models/active-session.model';\r\n\r\n// Phase 2 β TranslationService\r\nexport * from './services/translation.service';\r\n\r\n// Phase 3 β Transformation Services\r\nexport * from './services/transformation.service';\r\nexport * from './services/advanced-test.transformation.service';\r\n\r\n// Phase 4 β RecordingService\r\nexport * from './utils/subject';\r\nexport * from './services/recording.service';\r\n\r\n// Phase 5 β PersistenceService\r\nexport * from './services/persistence.service';\r\n\r\n// Phase 6 β HttpMonitor\r\nexport * from './services/http-monitor';\r\n\r\n// Phase 7 β UI Utilities\r\nexport * from './utils/styles.utils';\r\nexport * from './utils/modal.utils';\r\nexport * from './utils/toast.utils';\r\nexport * from './utils/export-selection.utils';\r\nexport * from './utils/host.utils';\r\n\r\n// Phase 8 β Web Components\r\nexport * from './components/selector-picker/selector-picker';\r\nexport * from './components/test-previsualizer/test-previsualizer';\r\nexport * from './components/save-test/save-test';\r\nexport * from './components/test-editor/test-editor';\r\nexport * from './components/configuration/configuration';\r\nexport * from './components/advanced-test-editor/advanced-test-editor';\r\nexport * from './components/file-preview/file-preview';\r\nexport * from './components/lib-e2e-recorder/lib-e2e-recorder';\r\n","export type Lang = 'es' | 'en' | 'fr' | 'it' | 'de';\r\n\r\nexport const SUPPORTED_LANGS: Lang[] = ['es', 'en', 'fr', 'it', 'de'];\r\n\r\nexport function isLang(value: string): value is Lang {\r\n return SUPPORTED_LANGS.includes(value as Lang);\r\n}\r\n\r\n/** BCP-47 locale used for date/number formatting per UI language. */\r\nexport const LOCALE_BY_LANG: Record<Lang, string> = {\r\n es: 'es-ES',\r\n en: 'en-GB',\r\n fr: 'fr-FR',\r\n it: 'it-IT',\r\n de: 'de-DE',\r\n};\r\n\r\n/** Returns the formatting locale for a UI language (falls back to es-ES). */\r\nexport function localeForLang(lang: string): string {\r\n return isLang(lang) ? LOCALE_BY_LANG[lang] : 'es-ES';\r\n}\r\n","export const INPUT_TYPES = [\r\n 'text',\r\n 'password',\r\n 'email',\r\n 'search',\r\n 'tel',\r\n 'url',\r\n 'number',\r\n 'textarea',\r\n] as const;\r\n\r\nexport type InputType = (typeof INPUT_TYPES)[number];\r\n","export interface DBStoreIndex {\r\n name: string;\r\n keyPath: string;\r\n unique: boolean;\r\n}\r\n\r\nexport interface DBStore {\r\n name: string;\r\n keyPath: string;\r\n autoIncrement: boolean;\r\n indexes: DBStoreIndex[];\r\n}\r\n\r\nexport interface DBSchema {\r\n name: string;\r\n version: number;\r\n stores: DBStore[];\r\n}\r\n\r\nexport const DB_SCHEMA: DBSchema = {\r\n name: 'E2ECypressDB',\r\n version: 11,\r\n stores: [\r\n {\r\n name: 'tests',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'name', keyPath: 'name', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'commands',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'command', keyPath: 'command', unique: false },\r\n { name: 'testId', keyPath: 'testId', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'interceptors',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'interceptor', keyPath: 'interceptor', unique: false },\r\n { name: 'testId', keyPath: 'testId', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'configuration',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'language', keyPath: 'language', unique: false },\r\n { name: 'extendedHttpCommands', keyPath: 'extendedHttpCommands', unique: false },\r\n { name: 'allowReadWriteFiles', keyPath: 'allowReadWriteFiles', unique: false },\r\n ],\r\n },\r\n {\r\n // Single-record store (fixed key id=1) holding the live, in-progress\r\n // recording session so it survives a micro-frontend crossing or reload.\r\n // See docs/specs/006-cross-app-recording-continuity.md.\r\n name: 'activeSession',\r\n keyPath: 'id',\r\n autoIncrement: false,\r\n indexes: [],\r\n },\r\n ],\r\n};\r\n\r\nexport const DB_STORE_NAMES = DB_SCHEMA.stores.map(s => s.name) as [\r\n 'tests',\r\n 'commands',\r\n 'interceptors',\r\n 'configuration',\r\n 'activeSession',\r\n];\r\n","import type { SelectorStrategy } from '../services/recording.service';\r\n\r\n/**\r\n * A live, in-progress recording session, persisted so it can survive a\r\n * micro-frontend crossing (single-spa app swap) or an accidental same-origin\r\n * reload. Only an actively-recording session is ever stored/resumed.\r\n *\r\n * The full payload lives in IndexedDB; a lightweight breadcrumb (sessionId +\r\n * isRecording + updatedAt) is mirrored to localStorage for synchronous detection.\r\n *\r\n * See docs/specs/006-cross-app-recording-continuity.md.\r\n */\r\nexport interface ActiveSessionState {\r\n /** Stable id for the session, generated when recording starts. */\r\n sessionId: string;\r\n isRecording: boolean;\r\n isPaused: boolean;\r\n commands: string[];\r\n interceptors: string[];\r\n selectorStrategy: SelectorStrategy;\r\n /** Epoch ms when the session started recording. */\r\n startedAt: number;\r\n /** Epoch ms of the last mutation β acts as the recency heartbeat. */\r\n updatedAt: number;\r\n}\r\n\r\n/** localStorage key for the synchronous \"is a session active?\" breadcrumb. */\r\nexport const ACTIVE_SESSION_BREADCRUMB_KEY = 'e2e-active-session';\r\n\r\n/** Configuration key (in the `configuration` store) for the resume recency TTL. */\r\nexport const RESUME_TTL_CONFIG_KEY = 'resumeRecencyTtlMinutes';\r\n\r\n/** Default minutes within which an active session resumes silently. */\r\nexport const DEFAULT_RESUME_TTL_MINUTES = 30;\r\n","export class Subject<T> {\r\n private _value: T;\r\n private listeners = new Set<(v: T) => void>();\r\n\r\n constructor(initialValue: T) {\r\n this._value = initialValue;\r\n }\r\n\r\n next(value: T): void {\r\n this._value = value;\r\n this.listeners.forEach((l) => l(value));\r\n }\r\n\r\n getValue(): T {\r\n return this._value;\r\n }\r\n\r\n subscribe(fn: (v: T) => void): () => void {\r\n this.listeners.add(fn);\r\n return () => this.listeners.delete(fn);\r\n }\r\n}\r\n","export const I18N_ES = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'ConfiguraciΓ³n',\r\n SHOW_ADVANCED_EDITOR: 'Editor avanzado',\r\n DIALOG_SAVED_TESTS: 'Pruebas guardadas',\r\n DIALOG_COMMANDS: 'Previsualizador de comandos Cypress',\r\n DIALOG_SAVE: 'ΒΏGuardar la grabaciΓ³n?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'DescripciΓ³n de la prueba',\r\n CANCEL: 'Cancelar',\r\n ASK: 'ΒΏGuardar el test grabado?',\r\n YES_CONTINUE: 'SΓ, continuar',\r\n NO_DISCARD: 'No, descartar',\r\n DESC_PLACEHOLDER: 'Ej: Login correcto con credenciales vΓ‘lidas',\r\n TAGS_LABEL: 'Etiquetas (opcional, para filtrar despuΓ©s):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regresiΓ³nβ¦',\r\n ADD_TAG: '+ AΓ±adir',\r\n NO_TAGS: 'Sin etiquetas',\r\n SAVE_BTN: 'πΎ Guardar',\r\n SAVE_AND_EDIT: 'π Guardar y editar',\r\n REMOVE_TAG_TITLE: 'Quitar',\r\n NOTES_LABEL: 'DescripciΓ³n / Notas (opcional):',\r\n NOTES_PLACEHOLDER: 'QuΓ© valida este test, condiciones previas, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Sin etiquetas',\r\n SELECTED_SINGULAR: 'seleccionado',\r\n SELECTED_PLURAL: 'seleccionados',\r\n DESCRIBE_PLACEHOLDER: 'Nombre del describe (opcional)',\r\n COPY_DESCRIBE: 'π Copiar describe()',\r\n MULTI_SELECT: 'π Multi-select',\r\n CANCEL_SELECT: 'β Cancelar',\r\n COPY_CMDS_BTN: 'π Copiar comandos',\r\n COPY_ICPS_BTN: 'π Copiar interceptores',\r\n DEFAULT_DESCRIBE: 'Suite de tests',\r\n NO_TESTS: 'No hay tests guardados',\r\n DELETE_TITLE: 'Eliminar',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Idioma',\r\n LANG_FIELD: 'Interfaz',\r\n HTTP_SECTION: 'β‘ HTTP Avanzado',\r\n HTTP_TITLE: 'Validaciones de body',\r\n HTTP_SUB: 'GET β response Β· POST/PUT β request',\r\n SELECTOR_SECTION: 'π― Estrategia de selector',\r\n SELECTOR_LABEL: 'Atributo preferido para cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (por defecto)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#elemento)',\r\n SELECTOR_HINT: 'El grabador buscarΓ‘ este atributo primero. Si no existe, intentarΓ‘ los demΓ‘s.',\r\n FOLDER_SECTION: 'π Carpeta Cypress',\r\n FOLDER_CONNECTED: 'conectado β',\r\n FOLDER_NOT_SET: 'sin configurar',\r\n FOLDER_CHANGE_BTN: 'π Cambiar carpeta',\r\n FOLDER_SELECT_BTN: 'π Seleccionar carpeta',\r\n FOLDER_REVOKE_BTN: 'β Quitar acceso',\r\n DATA_SECTION: 'πΎ Datos',\r\n DATA_DESC: 'Exporta todos tus tests a JSON o importa una copia de seguridad.',\r\n EXPORT_BTN: 'β¬οΈ Exportar tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Exportar tests',\r\n EXPORT_MODE_ALL: 'Todo',\r\n EXPORT_MODE_MANUAL: 'SelecciΓ³n manual',\r\n EXPORT_MODE_TAGS: 'Por tags',\r\n EXPORT_ALL_DESC: 'Se exportarΓ‘n todos los tests guardados.',\r\n EXPORT_COUNT: 'A exportar:',\r\n EXPORT_CONFIRM: 'β¬οΈ Exportar',\r\n EXPORT_CANCEL: 'Cancelar',\r\n EXPORT_EMPTY: 'No hay tests para exportar.',\r\n EXPORT_NO_TAGS: 'No hay tags disponibles.',\r\n EXPORT_TAGS_HINT: 'Selecciona uno o mΓ‘s tags para ver quΓ© pruebas se exportarΓ‘n.',\r\n EXPORT_RESULT_LABEL: 'Pruebas que se exportarΓ‘n:',\r\n IMPORT_BTN: 'β¬οΈ Importar tests',\r\n FOLDER_UPDATED_TOAST: 'β Carpeta de Cypress actualizada',\r\n FOLDER_ERROR_TOAST: 'Error al acceder a la carpeta',\r\n IMPORT_SUCCESS: 'Datos importados correctamente.',\r\n IMPORT_ERROR: 'Error al importar.',\r\n JSON_INVALID: 'El archivo no es un JSON vΓ‘lido.',\r\n JSON_BAD_FORMAT: 'El archivo no tiene el formato esperado.',\r\n SMART_SELECTOR_SECTION: 'π Selector inteligente',\r\n SMART_SELECTOR_TITLE: 'Selector inteligente',\r\n SMART_SELECTOR_SUB: 'Muestra un picker al hacer click en elementos sin selector vΓ‘lido.',\r\n START_HIDDEN_SECTION: 'π Visibilidad del widget',\r\n START_HIDDEN_TITLE: 'Iniciar oculto',\r\n START_HIDDEN_SUB: 'El widget arranca invisible. Usa Ctrl+Shift+E para mostrarlo u ocultarlo.',\r\n RESUME_TTL_SECTION: 'β± Continuidad de grabaciΓ³n',\r\n RESUME_TTL_LABEL: 'Reanudar sin preguntar (minutos)',\r\n RESUME_TTL_HINT: 'Si recargas o cambias de proyecto, una grabaciΓ³n activa se reanuda sin preguntar dentro de este margen. Pasado ese tiempo, te preguntarΓ‘ si continuar o descartar.',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Selecciona un elemento del DOM',\r\n PREVIEW_LABEL: 'navegar',\r\n CONFIRM_HINT: 'confirmar',\r\n CANCEL_HINT: 'cancelar',\r\n QUALITY_EXCELLENT: 'Excelente β tiene atributo de prueba (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Bueno β tiene un id vΓ‘lido',\r\n QUALITY_ACCEPTABLE: 'Aceptable β solo tiene clases CSS',\r\n QUALITY_POOR: 'No recomendado β solo tag o estilo inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptores',\r\n COPY_CMDS_BTN: 'π Copiar comandos',\r\n SHOW_INTERCEPTORS: 'βΌ Ver interceptores',\r\n HIDE_INTERCEPTORS: 'β² Ocultar interceptores',\r\n SECTION_COMMANDS: 'Comandos',\r\n NO_CMDS_YET: 'Sin comandos aΓΊn',\r\n NO_ICP_SHORT: 'Sin interceptores',\r\n COPY_ICP_BTN: 'π Copiar interceptores',\r\n UP_TITLE: 'Subir',\r\n DOWN_TITLE: 'Bajar',\r\n DEL_TITLE: 'Eliminar',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Reactivar acceso',\r\n PERMISSION_EXPIRED: 'π El permiso ha caducado',\r\n PERMISSION_EXPIRED_HINT: 'Haz clic para reactivar el acceso a tu carpeta de Cypress.',\r\n NO_ACCESS: 'π Sin acceso a archivos locales',\r\n NO_ACCESS_HINT: 'Configura el acceso en βοΈ Config.',\r\n NO_FILES: 'Sin archivos',\r\n SELECT_FILE: 'β Selecciona un archivo del Γ‘rbol',\r\n IT_LABEL: 'π§ͺ it() a insertar:',\r\n COPY_IT_BTN: 'π Copiar it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptores:',\r\n COPY_ICP_BTN: 'π Copiar interceptores',\r\n INSERT_BTN: 'πΎ Insertar en archivo',\r\n EDIT_MANUAL_BTN: 'βοΈ Editar manualmente',\r\n CLOSE_BTN: 'β Cerrar',\r\n NEW_FILE_BTN: '+ Nuevo archivo',\r\n NEW_FOLDER_BTN: '+ Nueva carpeta',\r\n REFRESH_BTN: 'β» Actualizar',\r\n NEW_FILE_PLACEHOLDER: 'nombre-del-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nombre-de-carpeta',\r\n NEW_FILE_CONFIRM: 'Crear',\r\n NEW_FILE_CANCEL: 'Cancelar',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Sin archivo',\r\n COPY_TITLE: 'Copiar contenido del editor',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copiar',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'Sin cambios respecto al original',\r\n NO_CHANGES_SHORT: 'Sin cambios',\r\n LAUNCH_BTN: 'βΆ Lanzar test',\r\n LAUNCH_LOCAL_ONLY: 'MuΓ©velo a local para poder probar',\r\n LAUNCH_RUNNING: 'β³ Ejecutandoβ¦',\r\n LAUNCH_PASSED: 'β Prueba superada',\r\n LAUNCH_FAILED: 'β Prueba fallida',\r\n LAUNCH_NO_RUNNER: 'No se detectΓ³ el runner local (ΒΏlo has arrancado?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Guardar',\r\n CLOSE_BTN: 'β Cerrar',\r\n BACK_TO_EDITOR: 'β Volver al editor',\r\n INSERT_BTN: 'πͺ Insertar bloques',\r\n INSERT_TITLE: 'Insertar it() y beforeEach() en el contenido del editor',\r\n INSERT_DONE: 'Bloques insertados en el editor',\r\n INSERT_ERROR: 'No se encontrΓ³ un bloque describe() vΓ‘lido en el archivo',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Acceso a ficheros',\r\n FS_LATER_BTN: 'Ahora no',\r\n FS_SELECT_BTN: 'π Seleccionar carpeta',\r\n FS_SUCCESS_TOAST: 'β Carpeta de Cypress configurada',\r\n FS_ERROR_TOAST: 'Error al acceder a la carpeta',\r\n FS_INTRO_HTML: 'El <strong style=\"color:#e6edf3\">editor avanzado</strong> puede insertar tus tests directamente en los archivos <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> de Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'Selecciona la carpeta que contiene la subcarpeta <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. La extensiΓ³n espera esta estructura:',\r\n FS_TREE_PICK_HINT: 'β selecciona esta carpeta',\r\n FS_TREE_READ_HINT: 'β la extensiΓ³n leerΓ‘ aquΓ',\r\n FS_PERMISSION_NOTE: 'El permiso se guarda en el navegador y no se vuelve a solicitar.',\r\n ASSERTION_SECTION: 'β AΓ±adir aserciΓ³n',\r\n ASSERT_SELECTOR_PH: 'selector, ej: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valor esperado',\r\n ASSERT_ADD_BTN: 'β AΓ±adir',\r\n FILE_EDITOR_TITLE: 'βοΈ Editor de archivo',\r\n FILE_SAVED_TOAST: 'β Archivo guardado',\r\n FILE_SAVE_ERROR_TOAST: 'Error al guardar el archivo',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Ficheros',\r\n BTN_COMMANDS: 'Comandos',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pausar (Ctrl+P)',\r\n RESUME_TITLE: 'Reanudar (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSA',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Detener (Ctrl+R)',\r\n START_TITLE: 'Grabar (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ GrabaciΓ³n en curso',\r\n SESSION_RESUME_TEXT: 'Hay una grabaciΓ³n activa sin terminar.',\r\n SESSION_RESUME_COUNT: 'comandos capturados',\r\n SESSION_CONTINUE_BTN: 'Continuar grabando',\r\n SESSION_DISCARD_BTN: 'Descartar',\r\n },\r\n};\r\n","export const I18N_EN = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Settings',\r\n SHOW_ADVANCED_EDITOR: 'Advanced editor',\r\n DIALOG_SAVED_TESTS: 'Saved tests',\r\n DIALOG_COMMANDS: 'Cypress commands previewer',\r\n DIALOG_SAVE: 'Save recording?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Test description',\r\n CANCEL: 'Cancel',\r\n ASK: 'Save the recorded test?',\r\n YES_CONTINUE: 'Yes, continue',\r\n NO_DISCARD: 'No, discard',\r\n DESC_PLACEHOLDER: 'E.g.: Successful login with valid credentials',\r\n TAGS_LABEL: 'Tags (optional, for later filtering):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressionβ¦',\r\n ADD_TAG: '+ Add',\r\n NO_TAGS: 'No tags',\r\n SAVE_BTN: 'πΎ Save',\r\n SAVE_AND_EDIT: 'π Save and edit',\r\n REMOVE_TAG_TITLE: 'Remove',\r\n NOTES_LABEL: 'Description / Notes (optional):',\r\n NOTES_PLACEHOLDER: 'What this test validates, preconditions, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'No tags',\r\n SELECTED_SINGULAR: 'selected',\r\n SELECTED_PLURAL: 'selected',\r\n DESCRIBE_PLACEHOLDER: 'describe name (optional)',\r\n COPY_DESCRIBE: 'π Copy describe()',\r\n MULTI_SELECT: 'π Multi-select',\r\n CANCEL_SELECT: 'β Cancel',\r\n COPY_CMDS_BTN: 'π Copy commands',\r\n COPY_ICPS_BTN: 'π Copy interceptors',\r\n DEFAULT_DESCRIBE: 'Test suite',\r\n NO_TESTS: 'No saved tests',\r\n DELETE_TITLE: 'Delete',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Language',\r\n LANG_FIELD: 'Interface',\r\n HTTP_SECTION: 'β‘ Advanced HTTP',\r\n HTTP_TITLE: 'Body validations',\r\n HTTP_SUB: 'GET β response Β· POST/PUT β request',\r\n SELECTOR_SECTION: 'π― Selector strategy',\r\n SELECTOR_LABEL: 'Preferred attribute for cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (default)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#element)',\r\n SELECTOR_HINT: 'The recorder will look for this attribute first. If not found, it will try the others.',\r\n FOLDER_SECTION: 'π Cypress Folder',\r\n FOLDER_CONNECTED: 'connected β',\r\n FOLDER_NOT_SET: 'not configured',\r\n FOLDER_CHANGE_BTN: 'π Change folder',\r\n FOLDER_SELECT_BTN: 'π Select folder',\r\n FOLDER_REVOKE_BTN: 'β Revoke access',\r\n DATA_SECTION: 'πΎ Data',\r\n DATA_DESC: 'Export all your tests to JSON or import a backup.',\r\n EXPORT_BTN: 'β¬οΈ Export tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Export tests',\r\n EXPORT_MODE_ALL: 'All',\r\n EXPORT_MODE_MANUAL: 'Manual selection',\r\n EXPORT_MODE_TAGS: 'By tags',\r\n EXPORT_ALL_DESC: 'All saved tests will be exported.',\r\n EXPORT_COUNT: 'To export:',\r\n EXPORT_CONFIRM: 'β¬οΈ Export',\r\n EXPORT_CANCEL: 'Cancel',\r\n EXPORT_EMPTY: 'No tests to export.',\r\n EXPORT_NO_TAGS: 'No tags available.',\r\n EXPORT_TAGS_HINT: 'Select one or more tags to preview which tests will be exported.',\r\n EXPORT_RESULT_LABEL: 'Tests that will be exported:',\r\n IMPORT_BTN: 'β¬οΈ Import tests',\r\n FOLDER_UPDATED_TOAST: 'β Cypress folder updated',\r\n FOLDER_ERROR_TOAST: 'Error accessing the folder',\r\n IMPORT_SUCCESS: 'Data imported successfully.',\r\n IMPORT_ERROR: 'Error importing.',\r\n JSON_INVALID: 'The file is not valid JSON.',\r\n JSON_BAD_FORMAT: 'The file does not have the expected format.',\r\n SMART_SELECTOR_SECTION: 'π Smart selector',\r\n SMART_SELECTOR_TITLE: 'Smart selector',\r\n SMART_SELECTOR_SUB: 'Shows a picker when clicking elements with no valid selector.',\r\n START_HIDDEN_SECTION: 'π Widget visibility',\r\n START_HIDDEN_TITLE: 'Start hidden',\r\n START_HIDDEN_SUB: 'The widget starts invisible. Use Ctrl+Shift+E to show or hide it.',\r\n RESUME_TTL_SECTION: 'β± Recording continuity',\r\n RESUME_TTL_LABEL: 'Resume without asking (minutes)',\r\n RESUME_TTL_HINT: 'If you reload or switch projects, an active recording resumes without asking within this window. After that, you will be asked to continue or discard.',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Select a DOM element',\r\n PREVIEW_LABEL: 'navigate',\r\n CONFIRM_HINT: 'confirm',\r\n CANCEL_HINT: 'cancel',\r\n QUALITY_EXCELLENT: 'Excellent β has a testing attribute (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Good β has a valid id',\r\n QUALITY_ACCEPTABLE: 'Acceptable β CSS classes only',\r\n QUALITY_POOR: 'Not recommended β tag name or inline style only',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptors',\r\n COPY_CMDS_BTN: 'π Copy commands',\r\n SHOW_INTERCEPTORS: 'βΌ Show interceptors',\r\n HIDE_INTERCEPTORS: 'β² Hide interceptors',\r\n SECTION_COMMANDS: 'Commands',\r\n NO_CMDS_YET: 'No commands yet',\r\n NO_ICP_SHORT: 'No interceptors',\r\n COPY_ICP_BTN: 'π Copy interceptors',\r\n UP_TITLE: 'Move up',\r\n DOWN_TITLE: 'Move down',\r\n DEL_TITLE: 'Delete',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Reactivate access',\r\n PERMISSION_EXPIRED: 'π Permission expired',\r\n PERMISSION_EXPIRED_HINT: 'Click to reactivate access to your Cypress folder.',\r\n NO_ACCESS: 'π No access to local files',\r\n NO_ACCESS_HINT: 'Configure access in βοΈ Config.',\r\n NO_FILES: 'No files',\r\n SELECT_FILE: 'β Select a file from the tree',\r\n IT_LABEL: 'π§ͺ it() to insert:',\r\n COPY_IT_BTN: 'π Copy it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptors:',\r\n COPY_ICP_BTN: 'π Copy interceptors',\r\n INSERT_BTN: 'πΎ Insert into file',\r\n EDIT_MANUAL_BTN: 'βοΈ Edit manually',\r\n CLOSE_BTN: 'β Close',\r\n NEW_FILE_BTN: '+ New file',\r\n NEW_FOLDER_BTN: '+ New folder',\r\n REFRESH_BTN: 'β» Refresh',\r\n NEW_FILE_PLACEHOLDER: 'test-name',\r\n NEW_FOLDER_PLACEHOLDER: 'folder-name',\r\n NEW_FILE_CONFIRM: 'Create',\r\n NEW_FILE_CANCEL: 'Cancel',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'No file',\r\n COPY_TITLE: 'Copy editor content',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copy',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'No changes from original',\r\n NO_CHANGES_SHORT: 'No changes',\r\n LAUNCH_BTN: 'βΆ Run test',\r\n LAUNCH_LOCAL_ONLY: 'Move it to localhost to run tests',\r\n LAUNCH_RUNNING: 'β³ Runningβ¦',\r\n LAUNCH_PASSED: 'β Test passed',\r\n LAUNCH_FAILED: 'β Test failed',\r\n LAUNCH_NO_RUNNER: 'No local runner detected (did you start it?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Save',\r\n CLOSE_BTN: 'β Close',\r\n BACK_TO_EDITOR: 'β Back to editor',\r\n INSERT_BTN: 'πͺ Insert blocks',\r\n INSERT_TITLE: 'Insert it() and beforeEach() into the editor content',\r\n INSERT_DONE: 'Blocks inserted into the editor',\r\n INSERT_ERROR: 'No valid describe() block found in the file',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π File access',\r\n FS_LATER_BTN: 'Not now',\r\n FS_SELECT_BTN: 'π Select folder',\r\n FS_SUCCESS_TOAST: 'β Cypress folder configured',\r\n FS_ERROR_TOAST: 'Error accessing the folder',\r\n FS_INTRO_HTML: 'The <strong style=\"color:#e6edf3\">advanced editor</strong> can insert your tests directly into the Cypress <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> files.',\r\n FS_STRUCTURE_HINT_HTML: 'Select the folder that contains the <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code> subfolder. The extension expects this structure:',\r\n FS_TREE_PICK_HINT: 'β select this folder',\r\n FS_TREE_READ_HINT: 'β the extension will read here',\r\n FS_PERMISSION_NOTE: 'The permission is stored in the browser and will not be requested again.',\r\n ASSERTION_SECTION: 'β Add assertion',\r\n ASSERT_SELECTOR_PH: 'selector, e.g.: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'expected value',\r\n ASSERT_ADD_BTN: 'β Add',\r\n FILE_EDITOR_TITLE: 'βοΈ File editor',\r\n FILE_SAVED_TOAST: 'β File saved',\r\n FILE_SAVE_ERROR_TOAST: 'Error saving the file',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Files',\r\n BTN_COMMANDS: 'Commands',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pause (Ctrl+P)',\r\n RESUME_TITLE: 'Resume (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSED',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Stop (Ctrl+R)',\r\n START_TITLE: 'Record (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Recording in progress',\r\n SESSION_RESUME_TEXT: 'There is an unfinished active recording.',\r\n SESSION_RESUME_COUNT: 'commands captured',\r\n SESSION_CONTINUE_BTN: 'Keep recording',\r\n SESSION_DISCARD_BTN: 'Discard',\r\n },\r\n};\r\n","export const I18N_FR = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'ParamΓ¨tres',\r\n SHOW_ADVANCED_EDITOR: 'Γditeur avancΓ©',\r\n DIALOG_SAVED_TESTS: 'Tests enregistrΓ©s',\r\n DIALOG_COMMANDS: 'AperΓ§u des commandes Cypress',\r\n DIALOG_SAVE: \"Enregistrer l'enregistrement ?\",\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Description du test',\r\n CANCEL: 'Annuler',\r\n ASK: 'Enregistrer le test ?',\r\n YES_CONTINUE: 'Oui, continuer',\r\n NO_DISCARD: 'Non, ignorer',\r\n DESC_PLACEHOLDER: 'Ex : Connexion rΓ©ussie avec identifiants valides',\r\n TAGS_LABEL: 'Γtiquettes (optionnel, pour filtrer ensuite) :',\r\n TAGS_PLACEHOLDER: 'smoke, login, rΓ©gressionβ¦',\r\n ADD_TAG: '+ Ajouter',\r\n NO_TAGS: 'Sans Γ©tiquettes',\r\n SAVE_BTN: 'πΎ Enregistrer',\r\n SAVE_AND_EDIT: 'π Enregistrer et Γ©diter',\r\n REMOVE_TAG_TITLE: 'Retirer',\r\n NOTES_LABEL: 'Description / Notes (optionnel) :',\r\n NOTES_PLACEHOLDER: 'Ce que ce test valide, conditions prΓ©alables, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Sans Γ©tiquettes',\r\n SELECTED_SINGULAR: 'sΓ©lectionnΓ©',\r\n SELECTED_PLURAL: 'sΓ©lectionnΓ©s',\r\n DESCRIBE_PLACEHOLDER: 'Nom du describe (optionnel)',\r\n COPY_DESCRIBE: 'π Copier describe()',\r\n MULTI_SELECT: 'π Multi-sΓ©lection',\r\n CANCEL_SELECT: 'β Annuler',\r\n COPY_CMDS_BTN: 'π Copier les commandes',\r\n COPY_ICPS_BTN: 'π Copier les intercepteurs',\r\n DEFAULT_DESCRIBE: 'Suite de tests',\r\n NO_TESTS: 'Aucun test enregistrΓ©',\r\n DELETE_TITLE: 'Supprimer',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Langue',\r\n LANG_FIELD: 'Interface',\r\n HTTP_SECTION: 'β‘ HTTP AvancΓ©',\r\n HTTP_TITLE: 'Validations du corps',\r\n HTTP_SUB: 'GET β rΓ©ponse Β· POST/PUT β requΓͺte',\r\n SELECTOR_SECTION: 'π― StratΓ©gie de sΓ©lecteur',\r\n SELECTOR_LABEL: 'Attribut prΓ©fΓ©rΓ© pour cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (par dΓ©faut)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#Γ©lΓ©ment)',\r\n SELECTOR_HINT: \"L'enregistreur cherchera d'abord cet attribut. Si absent, il essaiera les autres.\",\r\n FOLDER_SECTION: 'π Dossier Cypress',\r\n FOLDER_CONNECTED: 'connectΓ© β',\r\n FOLDER_NOT_SET: 'non configurΓ©',\r\n FOLDER_CHANGE_BTN: 'π Changer de dossier',\r\n FOLDER_SELECT_BTN: 'π SΓ©lectionner un dossier',\r\n FOLDER_REVOKE_BTN: \"β RΓ©voquer l'accΓ¨s\",\r\n DATA_SECTION: 'πΎ DonnΓ©es',\r\n DATA_DESC: 'Exportez tous vos tests en JSON ou importez une sauvegarde.',\r\n EXPORT_BTN: 'β¬οΈ Exporter les tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Exporter les tests',\r\n EXPORT_MODE_ALL: 'Tout',\r\n EXPORT_MODE_MANUAL: 'SΓ©lection manuelle',\r\n EXPORT_MODE_TAGS: 'Par tags',\r\n EXPORT_ALL_DESC: 'Tous les tests enregistrΓ©s seront exportΓ©s.',\r\n EXPORT_COUNT: 'Γ exporter :',\r\n EXPORT_CONFIRM: 'β¬οΈ Exporter',\r\n EXPORT_CANCEL: 'Annuler',\r\n EXPORT_EMPTY: 'Aucun test Γ exporter.',\r\n EXPORT_NO_TAGS: 'Aucun tag disponible.',\r\n EXPORT_TAGS_HINT: 'SΓ©lectionnez un ou plusieurs tags pour voir les tests qui seront exportΓ©s.',\r\n EXPORT_RESULT_LABEL: 'Tests qui seront exportΓ©s :',\r\n IMPORT_BTN: 'β¬οΈ Importer les tests',\r\n FOLDER_UPDATED_TOAST: 'β Dossier Cypress mis Γ jour',\r\n FOLDER_ERROR_TOAST: \"Erreur lors de l'accΓ¨s au dossier\",\r\n IMPORT_SUCCESS: 'DonnΓ©es importΓ©es avec succΓ¨s.',\r\n IMPORT_ERROR: \"Erreur lors de l'importation.\",\r\n JSON_INVALID: \"Le fichier n'est pas un JSON valide.\",\r\n JSON_BAD_FORMAT: \"Le fichier n'a pas le format attendu.\",\r\n SMART_SELECTOR_SECTION: 'π SΓ©lecteur intelligent',\r\n SMART_SELECTOR_TITLE: 'SΓ©lecteur intelligent',\r\n SMART_SELECTOR_SUB: 'Affiche un sΓ©lecteur lors du clic sur des Γ©lΓ©ments sans sΓ©lecteur valide.',\r\n START_HIDDEN_SECTION: 'π VisibilitΓ© du widget',\r\n START_HIDDEN_TITLE: 'DΓ©marrer masquΓ©',\r\n START_HIDDEN_SUB: 'Le widget dΓ©marre invisible. Utilisez Ctrl+Shift+E pour l\\'afficher ou le masquer.',\r\n RESUME_TTL_SECTION: 'β± ContinuitΓ© d\\'enregistrement',\r\n RESUME_TTL_LABEL: 'Reprendre sans demander (minutes)',\r\n RESUME_TTL_HINT: 'Si vous rechargez ou changez de projet, un enregistrement actif reprend sans demander dans ce dΓ©lai. Au-delΓ , il vous demandera de continuer ou d\\'ignorer.',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'SΓ©lectionnez un Γ©lΓ©ment du DOM',\r\n PREVIEW_LABEL: 'naviguer',\r\n CONFIRM_HINT: 'confirmer',\r\n CANCEL_HINT: 'annuler',\r\n QUALITY_EXCELLENT: 'Excellent β attribut de test prΓ©sent (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Bon β id valide',\r\n QUALITY_ACCEPTABLE: 'Acceptable β classes CSS uniquement',\r\n QUALITY_POOR: 'DΓ©conseillΓ© β seulement le nom de balise ou style inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Intercepteurs',\r\n COPY_CMDS_BTN: 'π Copier les commandes',\r\n SHOW_INTERCEPTORS: 'βΌ Voir les intercepteurs',\r\n HIDE_INTERCEPTORS: 'β² Masquer les intercepteurs',\r\n SECTION_COMMANDS: 'Commandes',\r\n NO_CMDS_YET: 'Aucune commande encore',\r\n NO_ICP_SHORT: 'Aucun intercepteur',\r\n COPY_ICP_BTN: 'π Copier les intercepteurs',\r\n UP_TITLE: 'Monter',\r\n DOWN_TITLE: 'Descendre',\r\n DEL_TITLE: 'Supprimer',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: \"π RΓ©activer l'accΓ¨s\",\r\n PERMISSION_EXPIRED: 'π Autorisation expirΓ©e',\r\n PERMISSION_EXPIRED_HINT: \"Cliquez pour rΓ©activer l'accΓ¨s Γ votre dossier Cypress.\",\r\n NO_ACCESS: 'π Pas d\\'accΓ¨s aux fichiers locaux',\r\n NO_ACCESS_HINT: \"Configurez l'accΓ¨s dans βοΈ Config.\",\r\n NO_FILES: 'Aucun fichier',\r\n SELECT_FILE: \"β SΓ©lectionnez un fichier dans l'arborescence\",\r\n IT_LABEL: 'π§ͺ it() Γ insΓ©rer :',\r\n COPY_IT_BTN: 'π Copier it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() intercepteurs :',\r\n COPY_ICP_BTN: 'π Copier les intercepteurs',\r\n INSERT_BTN: 'πΎ InsΓ©rer dans le fichier',\r\n EDIT_MANUAL_BTN: 'βοΈ Γditer manuellement',\r\n CLOSE_BTN: 'β Fermer',\r\n NEW_FILE_BTN: '+ Nouveau fichier',\r\n NEW_FOLDER_BTN: '+ Nouveau dossier',\r\n REFRESH_BTN: 'β» Actualiser',\r\n NEW_FILE_PLACEHOLDER: 'nom-du-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nom-du-dossier',\r\n NEW_FILE_CONFIRM: 'CrΓ©er',\r\n NEW_FILE_CANCEL: 'Annuler',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Sans fichier',\r\n COPY_TITLE: \"Copier le contenu de l'Γ©diteur\",\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copier',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: \"Aucun changement par rapport Γ l'original\",\r\n NO_CHANGES_SHORT: 'Aucun changement',\r\n LAUNCH_BTN: 'βΆ Lancer le test',\r\n LAUNCH_LOCAL_ONLY: 'Passe en local pour pouvoir tester',\r\n LAUNCH_RUNNING: 'β³ ExΓ©cutionβ¦',\r\n LAUNCH_PASSED: 'β Test rΓ©ussi',\r\n LAUNCH_FAILED: 'β Test Γ©chouΓ©',\r\n LAUNCH_NO_RUNNER: \"Aucun runner local dΓ©tectΓ© (l'avez-vous dΓ©marrΓ© ?)\",\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Enregistrer',\r\n CLOSE_BTN: 'β Fermer',\r\n BACK_TO_EDITOR: \"β Retour Γ l'Γ©diteur\",\r\n INSERT_BTN: 'πͺ InsΓ©rer les blocs',\r\n INSERT_TITLE: \"InsΓ©rer it() et beforeEach() dans le contenu de l'Γ©diteur\",\r\n INSERT_DONE: \"Blocs insΓ©rΓ©s dans l'Γ©diteur\",\r\n INSERT_ERROR: 'Aucun bloc describe() valide trouvΓ© dans le fichier',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π AccΓ¨s aux fichiers',\r\n FS_LATER_BTN: 'Pas maintenant',\r\n FS_SELECT_BTN: 'π SΓ©lectionner un dossier',\r\n FS_SUCCESS_TOAST: 'β Dossier Cypress configurΓ©',\r\n FS_ERROR_TOAST: \"Erreur lors de l'accΓ¨s au dossier\",\r\n FS_INTRO_HTML: 'L\\'<strong style=\"color:#e6edf3\">Γ©diteur avancΓ©</strong> peut insΓ©rer vos tests directement dans les fichiers <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> de Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'SΓ©lectionnez le dossier qui contient le sous-dossier <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. L\\'extension attend cette structure :',\r\n FS_TREE_PICK_HINT: 'β sΓ©lectionnez ce dossier',\r\n FS_TREE_READ_HINT: 'β l\\'extension lira ici',\r\n FS_PERMISSION_NOTE: 'L\\'autorisation est enregistrΓ©e dans le navigateur et ne sera plus demandΓ©e.',\r\n ASSERTION_SECTION: 'β Ajouter une assertion',\r\n ASSERT_SELECTOR_PH: 'sΓ©lecteur, ex : [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valeur attendue',\r\n ASSERT_ADD_BTN: 'β Ajouter',\r\n FILE_EDITOR_TITLE: 'βοΈ Γditeur de fichier',\r\n FILE_SAVED_TOAST: 'β Fichier enregistrΓ©',\r\n FILE_SAVE_ERROR_TOAST: \"Erreur lors de l'enregistrement\",\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Fichiers',\r\n BTN_COMMANDS: 'Commandes',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pause (Ctrl+P)',\r\n RESUME_TITLE: 'Reprendre (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSE',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'ArrΓͺter (Ctrl+R)',\r\n START_TITLE: 'Enregistrer (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Enregistrement en cours',\r\n SESSION_RESUME_TEXT: 'Un enregistrement actif est inachevΓ©.',\r\n SESSION_RESUME_COUNT: 'commandes capturΓ©es',\r\n SESSION_CONTINUE_BTN: 'Continuer l\\'enregistrement',\r\n SESSION_DISCARD_BTN: 'Ignorer',\r\n },\r\n};\r\n","export const I18N_IT = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Impostazioni',\r\n SHOW_ADVANCED_EDITOR: 'Editor avanzato',\r\n DIALOG_SAVED_TESTS: 'Test salvati',\r\n DIALOG_COMMANDS: 'Anteprima comandi Cypress',\r\n DIALOG_SAVE: 'Salvare la registrazione?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Descrizione del test',\r\n CANCEL: 'Annulla',\r\n ASK: 'Salvare il test registrato?',\r\n YES_CONTINUE: 'SΓ¬, continua',\r\n NO_DISCARD: 'No, annulla',\r\n DESC_PLACEHOLDER: 'Es: Login riuscito con credenziali valide',\r\n TAGS_LABEL: 'Etichette (opzionale, per filtrare dopo):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressioneβ¦',\r\n ADD_TAG: '+ Aggiungi',\r\n NO_TAGS: 'Nessuna etichetta',\r\n SAVE_BTN: 'πΎ Salva',\r\n SAVE_AND_EDIT: 'π Salva e modifica',\r\n REMOVE_TAG_TITLE: 'Rimuovi',\r\n NOTES_LABEL: 'Descrizione / Note (opzionale):',\r\n NOTES_PLACEHOLDER: 'Cosa valida questo test, condizioni preliminari, ecc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Nessuna etichetta',\r\n SELECTED_SINGULAR: 'selezionato',\r\n SELECTED_PLURAL: 'selezionati',\r\n DESCRIBE_PLACEHOLDER: 'Nome del describe (opzionale)',\r\n COPY_DESCRIBE: 'π Copia describe()',\r\n MULTI_SELECT: 'π Multi-selezione',\r\n CANCEL_SELECT: 'β Annulla',\r\n COPY_CMDS_BTN: 'π Copia comandi',\r\n COPY_ICPS_BTN: 'π Copia interceptor',\r\n DEFAULT_DESCRIBE: 'Suite di test',\r\n NO_TESTS: 'Nessun test salvato',\r\n DELETE_TITLE: 'Elimina',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Lingua',\r\n LANG_FIELD: 'Interfaccia',\r\n HTTP_SECTION: 'β‘ HTTP Avanzato',\r\n HTTP_TITLE: 'Validazioni del body',\r\n HTTP_SUB: 'GET β risposta Β· POST/PUT β richiesta',\r\n SELECTOR_SECTION: 'π― Strategia selettore',\r\n SELECTOR_LABEL: 'Attributo preferito per cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (predefinito)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#elemento)',\r\n SELECTOR_HINT: 'Il registratore cercherΓ prima questo attributo. Se assente, proverΓ gli altri.',\r\n FOLDER_SECTION: 'π Cartella Cypress',\r\n FOLDER_CONNECTED: 'connesso β',\r\n FOLDER_NOT_SET: 'non configurato',\r\n FOLDER_CHANGE_BTN: 'π Cambia cartella',\r\n FOLDER_SELECT_BTN: 'π Seleziona cartella',\r\n FOLDER_REVOKE_BTN: 'β Revoca accesso',\r\n DATA_SECTION: 'πΎ Dati',\r\n DATA_DESC: 'Esporta tutti i tuoi test in JSON o importa un backup.',\r\n EXPORT_BTN: 'β¬οΈ Esporta test',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Esporta test',\r\n EXPORT_MODE_ALL: 'Tutto',\r\n EXPORT_MODE_MANUAL: 'Selezione manuale',\r\n EXPORT_MODE_TAGS: 'Per tag',\r\n EXPORT_ALL_DESC: 'Verranno esportati tutti i test salvati.',\r\n EXPORT_COUNT: 'Da esportare:',\r\n EXPORT_CONFIRM: 'β¬οΈ Esporta',\r\n EXPORT_CANCEL: 'Annulla',\r\n EXPORT_EMPTY: 'Nessun test da esportare.',\r\n EXPORT_NO_TAGS: 'Nessun tag disponibile.',\r\n EXPORT_TAGS_HINT: 'Seleziona uno o piΓΉ tag per vedere quali test verranno esportati.',\r\n EXPORT_RESULT_LABEL: 'Test che verranno esportati:',\r\n IMPORT_BTN: 'β¬οΈ Importa test',\r\n FOLDER_UPDATED_TOAST: 'β Cartella Cypress aggiornata',\r\n FOLDER_ERROR_TOAST: \"Errore durante l'accesso alla cartella\",\r\n IMPORT_SUCCESS: 'Dati importati correttamente.',\r\n IMPORT_ERROR: \"Errore durante l'importazione.\",\r\n JSON_INVALID: 'Il file non Γ¨ un JSON valido.',\r\n JSON_BAD_FORMAT: 'Il file non ha il formato previsto.',\r\n SMART_SELECTOR_SECTION: 'π Selettore intelligente',\r\n SMART_SELECTOR_TITLE: 'Selettore intelligente',\r\n SMART_SELECTOR_SUB: 'Mostra un selettore quando si fa clic su elementi senza selettore valido.',\r\n START_HIDDEN_SECTION: 'π VisibilitΓ del widget',\r\n START_HIDDEN_TITLE: 'Avvia nascosto',\r\n START_HIDDEN_SUB: 'Il widget si avvia invisibile. Usa Ctrl+Shift+E per mostrarlo o nasconderlo.',\r\n RESUME_TTL_SECTION: 'β± ContinuitΓ di registrazione',\r\n RESUME_TTL_LABEL: 'Riprendi senza chiedere (minuti)',\r\n RESUME_TTL_HINT: 'Se ricarichi o cambi progetto, una registrazione attiva riprende senza chiedere entro questo intervallo. Trascorso, ti chiederΓ se continuare o annullare.',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Seleziona un elemento DOM',\r\n PREVIEW_LABEL: 'navigare',\r\n CONFIRM_HINT: 'confermare',\r\n CANCEL_HINT: 'annullare',\r\n QUALITY_EXCELLENT: 'Eccellente β attributo di test presente (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Buono β id valido',\r\n QUALITY_ACCEPTABLE: 'Accettabile β solo classi CSS',\r\n QUALITY_POOR: 'Sconsigliato β solo tag o stile inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptor',\r\n COPY_CMDS_BTN: 'π Copia comandi',\r\n SHOW_INTERCEPTORS: 'βΌ Vedi interceptor',\r\n HIDE_INTERCEPTORS: 'β² Nascondi interceptor',\r\n SECTION_COMMANDS: 'Comandi',\r\n NO_CMDS_YET: 'Ancora nessun comando',\r\n NO_ICP_SHORT: 'Nessun interceptor',\r\n COPY_ICP_BTN: 'π Copia interceptor',\r\n UP_TITLE: 'Su',\r\n DOWN_TITLE: 'GiΓΉ',\r\n DEL_TITLE: 'Elimina',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Riattiva accesso',\r\n PERMISSION_EXPIRED: 'π Autorizzazione scaduta',\r\n PERMISSION_EXPIRED_HINT: \"Clicca per riattivare l'accesso alla cartella Cypress.\",\r\n NO_ACCESS: 'π Nessun accesso ai file locali',\r\n NO_ACCESS_HINT: \"Configura l'accesso in βοΈ Config.\",\r\n NO_FILES: 'Nessun file',\r\n SELECT_FILE: \"β Seleziona un file dall'albero\",\r\n IT_LABEL: 'π§ͺ it() da inserire:',\r\n COPY_IT_BTN: 'π Copia it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptor:',\r\n COPY_ICP_BTN: 'π Copia interceptor',\r\n INSERT_BTN: 'πΎ Inserisci nel file',\r\n EDIT_MANUAL_BTN: 'βοΈ Modifica manualmente',\r\n CLOSE_BTN: 'β Chiudi',\r\n NEW_FILE_BTN: '+ Nuovo file',\r\n NEW_FOLDER_BTN: '+ Nuova cartella',\r\n REFRESH_BTN: 'β» Aggiorna',\r\n NEW_FILE_PLACEHOLDER: 'nome-del-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nome-cartella',\r\n NEW_FILE_CONFIRM: 'Crea',\r\n NEW_FILE_CANCEL: 'Annulla',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Nessun file',\r\n COPY_TITLE: \"Copia il contenuto dell'editor\",\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copia',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: \"Nessuna modifica rispetto all'originale\",\r\n NO_CHANGES_SHORT: 'Nessuna modifica',\r\n LAUNCH_BTN: 'βΆ Esegui test',\r\n LAUNCH_LOCAL_ONLY: 'Spostati in locale per poter testare',\r\n LAUNCH_RUNNING: 'β³ Esecuzioneβ¦',\r\n LAUNCH_PASSED: 'β Test superato',\r\n LAUNCH_FAILED: 'β Test fallito',\r\n LAUNCH_NO_RUNNER: \"Nessun runner locale rilevato (l'hai avviato?)\",\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Salva',\r\n CLOSE_BTN: 'β Chiudi',\r\n BACK_TO_EDITOR: \"β Torna all'editor\",\r\n INSERT_BTN: 'πͺ Inserisci blocchi',\r\n INSERT_TITLE: \"Inserisci it() e beforeEach() nel contenuto dell'editor\",\r\n INSERT_DONE: \"Blocchi inseriti nell'editor\",\r\n INSERT_ERROR: 'Nessun blocco describe() valido trovato nel file',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Accesso ai file',\r\n FS_LATER_BTN: 'Non ora',\r\n FS_SELECT_BTN: 'π Seleziona cartella',\r\n FS_SUCCESS_TOAST: 'β Cartella Cypress configurata',\r\n FS_ERROR_TOAST: \"Errore durante l'accesso alla cartella\",\r\n FS_INTRO_HTML: 'L\\'<strong style=\"color:#e6edf3\">editor avanzato</strong> puΓ² inserire i tuoi test direttamente nei file <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> di Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'Seleziona la cartella che contiene la sottocartella <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. L\\'estensione si aspetta questa struttura:',\r\n FS_TREE_PICK_HINT: 'β seleziona questa cartella',\r\n FS_TREE_READ_HINT: 'β l\\'estensione leggerΓ qui',\r\n FS_PERMISSION_NOTE: 'Il permesso viene salvato nel browser e non sarΓ richiesto di nuovo.',\r\n ASSERTION_SECTION: 'β Aggiungi asserzione',\r\n ASSERT_SELECTOR_PH: 'selettore, es: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valore atteso',\r\n ASSERT_ADD_BTN: 'β Aggiungi',\r\n FILE_EDITOR_TITLE: 'βοΈ Editor di file',\r\n FILE_SAVED_TOAST: 'β File salvato',\r\n FILE_SAVE_ERROR_TOAST: 'Errore durante il salvataggio',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'File',\r\n BTN_COMMANDS: 'Comandi',\r\n BTN_TESTS: 'Test',\r\n PAUSE_TITLE: 'Pausa (Ctrl+P)',\r\n RESUME_TITLE: 'Riprendi (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSA',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Ferma (Ctrl+R)',\r\n START_TITLE: 'Registra (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Registrazione in corso',\r\n SESSION_RESUME_TEXT: 'C\\'Γ¨ una registrazione attiva non terminata.',\r\n SESSION_RESUME_COUNT: 'comandi catturati',\r\n SESSION_CONTINUE_BTN: 'Continua a registrare',\r\n SESSION_DISCARD_BTN: 'Annulla',\r\n },\r\n};\r\n","export const I18N_DE = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Einstellungen',\r\n SHOW_ADVANCED_EDITOR: 'Erweiterter Editor',\r\n DIALOG_SAVED_TESTS: 'Gespeicherte Tests',\r\n DIALOG_COMMANDS: 'Cypress-Befehle Vorschau',\r\n DIALOG_SAVE: 'Aufzeichnung speichern?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Testbeschreibung',\r\n CANCEL: 'Abbrechen',\r\n ASK: 'Aufgezeichneten Test speichern?',\r\n YES_CONTINUE: 'Ja, weiter',\r\n NO_DISCARD: 'Nein, verwerfen',\r\n DESC_PLACEHOLDER: 'Z. B.: Erfolgreiche Anmeldung mit gΓΌltigen Zugangsdaten',\r\n TAGS_LABEL: 'Tags (optional, zum spΓ€teren Filtern):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressionβ¦',\r\n ADD_TAG: '+ HinzufΓΌgen',\r\n NO_TAGS: 'Keine Tags',\r\n SAVE_BTN: 'πΎ Speichern',\r\n SAVE_AND_EDIT: 'π Speichern und bearbeiten',\r\n REMOVE_TAG_TITLE: 'Entfernen',\r\n NOTES_LABEL: 'Beschreibung / Notizen (optional):',\r\n NOTES_PLACEHOLDER: 'Was dieser Test validiert, Voraussetzungen usw.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Keine Tags',\r\n SELECTED_SINGULAR: 'ausgewΓ€hlt',\r\n SELECTED_PLURAL: 'ausgewΓ€hlt',\r\n DESCRIBE_PLACEHOLDER: 'describe-Name (optional)',\r\n COPY_DESCRIBE: 'π describe() kopieren',\r\n MULTI_SELECT: 'π Mehrfachauswahl',\r\n CANCEL_SELECT: 'β Abbrechen',\r\n COPY_CMDS_BTN: 'π Befehle kopieren',\r\n COPY_ICPS_BTN: 'π Interceptors kopieren',\r\n DEFAULT_DESCRIBE: 'Test-Suite',\r\n NO_TESTS: 'Keine gespeicherten Tests',\r\n DELETE_TITLE: 'LΓΆschen',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Sprache',\r\n LANG_FIELD: 'OberflΓ€che',\r\n HTTP_SECTION: 'β‘ Erweitertes HTTP',\r\n HTTP_TITLE: 'Body-Validierungen',\r\n HTTP_SUB: 'GET β Antwort Β· POST/PUT β Anfrage',\r\n SELECTOR_SECTION: 'π― Selector-Strategie',\r\n SELECTOR_LABEL: 'Bevorzugtes Attribut fΓΌr cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (Standard)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#element)',\r\n SELECTOR_HINT: 'Der Recorder sucht zuerst nach diesem Attribut. Falls nicht gefunden, versucht er die anderen.',\r\n FOLDER_SECTION: 'π Cypress-Ordner',\r\n FOLDER_CONNECTED: 'verbunden β',\r\n FOLDER_NOT_SET: 'nicht konfiguriert',\r\n FOLDER_CHANGE_BTN: 'π Ordner wechseln',\r\n FOLDER_SELECT_BTN: 'π Ordner auswΓ€hlen',\r\n FOLDER_REVOKE_BTN: 'β Zugriff widerrufen',\r\n DATA_SECTION: 'πΎ Daten',\r\n DATA_DESC: 'Exportieren Sie alle Tests als JSON oder importieren Sie ein Backup.',\r\n EXPORT_BTN: 'β¬οΈ Tests exportieren',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Tests exportieren',\r\n EXPORT_MODE_ALL: 'Alle',\r\n EXPORT_MODE_MANUAL: 'Manuelle Auswahl',\r\n EXPORT_MODE_TAGS: 'Nach Tags',\r\n EXPORT_ALL_DESC: 'Alle gespeicherten Tests werden exportiert.',\r\n EXPORT_COUNT: 'Zu exportieren:',\r\n EXPORT_CONFIRM: 'β¬οΈ Exportieren',\r\n EXPORT_CANCEL: 'Abbrechen',\r\n EXPORT_EMPTY: 'Keine Tests zum Exportieren.',\r\n EXPORT_NO_TAGS: 'Keine Tags verfΓΌgbar.',\r\n EXPORT_TAGS_HINT: 'WΓ€hle ein oder mehrere Tags, um zu sehen, welche Tests exportiert werden.',\r\n EXPORT_RESULT_LABEL: 'Diese Tests werden exportiert:',\r\n IMPORT_BTN: 'β¬οΈ Tests importieren',\r\n FOLDER_UPDATED_TOAST: 'β Cypress-Ordner aktualisiert',\r\n FOLDER_ERROR_TOAST: 'Fehler beim Zugriff auf den Ordner',\r\n IMPORT_SUCCESS: 'Daten erfolgreich importiert.',\r\n IMPORT_ERROR: 'Fehler beim Importieren.',\r\n JSON_INVALID: 'Die Datei ist kein gΓΌltiges JSON.',\r\n JSON_BAD_FORMAT: 'Die Datei hat nicht das erwartete Format.',\r\n SMART_SELECTOR_SECTION: 'π Intelligenter Selektor',\r\n SMART_SELECTOR_TITLE: 'Intelligenter Selektor',\r\n SMART_SELECTOR_SUB: 'Zeigt ein Auswahlfeld, wenn auf Elemente ohne gΓΌltigen Selektor geklickt wird.',\r\n START_HIDDEN_SECTION: 'π Widget-Sichtbarkeit',\r\n START_HIDDEN_TITLE: 'Versteckt starten',\r\n START_HIDDEN_SUB: 'Das Widget startet unsichtbar. Verwenden Sie Ctrl+Shift+E zum Ein-/Ausblenden.',\r\n RESUME_TTL_SECTION: 'β± AufzeichnungskontinuitΓ€t',\r\n RESUME_TTL_LABEL: 'Ohne Nachfrage fortsetzen (Minuten)',\r\n RESUME_TTL_HINT: 'Wenn Sie neu laden oder das Projekt wechseln, wird eine aktive Aufzeichnung innerhalb dieses Zeitfensters ohne Nachfrage fortgesetzt. Danach werden Sie gefragt, ob fortsetzen oder verwerfen.',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'DOM-Element auswΓ€hlen',\r\n PREVIEW_LABEL: 'navigieren',\r\n CONFIRM_HINT: 'bestΓ€tigen',\r\n CANCEL_HINT: 'abbrechen',\r\n QUALITY_EXCELLENT: 'Ausgezeichnet β Test-Attribut vorhanden (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Gut β gΓΌltige ID',\r\n QUALITY_ACCEPTABLE: 'Akzeptabel β nur CSS-Klassen',\r\n QUALITY_POOR: 'Nicht empfohlen β nur Tag oder Inline-Style',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptors',\r\n COPY_CMDS_BTN: 'π Befehle kopieren',\r\n SHOW_INTERCEPTORS: 'βΌ Interceptors anzeigen',\r\n HIDE_INTERCEPTORS: 'β² Interceptors ausblenden',\r\n SECTION_COMMANDS: 'Befehle',\r\n NO_CMDS_YET: 'Noch keine Befehle',\r\n NO_ICP_SHORT: 'Keine Interceptors',\r\n COPY_ICP_BTN: 'π Interceptors kopieren',\r\n UP_TITLE: 'Nach oben',\r\n DOWN_TITLE: 'Nach unten',\r\n DEL_TITLE: 'LΓΆschen',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Zugriff reaktivieren',\r\n PERMISSION_EXPIRED: 'π Berechtigung abgelaufen',\r\n PERMISSION_EXPIRED_HINT: 'Klicken Sie, um den Zugriff auf Ihren Cypress-Ordner zu reaktivieren.',\r\n NO_ACCESS: 'π Kein Zugriff auf lokale Dateien',\r\n NO_ACCESS_HINT: 'Konfigurieren Sie den Zugriff unter βοΈ Config.',\r\n NO_FILES: 'Keine Dateien',\r\n SELECT_FILE: 'β WΓ€hlen Sie eine Datei aus dem Baum',\r\n IT_LABEL: 'π§ͺ it() zum EinfΓΌgen:',\r\n COPY_IT_BTN: 'π it() kopieren',\r\n BEFORE_EACH_LABEL: 'π beforeEach() Interceptors:',\r\n COPY_ICP_BTN: 'π Interceptors kopieren',\r\n INSERT_BTN: 'πΎ In Datei einfΓΌgen',\r\n EDIT_MANUAL_BTN: 'βοΈ Manuell bearbeiten',\r\n CLOSE_BTN: 'β SchlieΓen',\r\n NEW_FILE_BTN: '+ Neue Datei',\r\n NEW_FOLDER_BTN: '+ Neuer Ordner',\r\n REFRESH_BTN: 'β» Aktualisieren',\r\n NEW_FILE_PLACEHOLDER: 'test-name',\r\n NEW_FOLDER_PLACEHOLDER: 'ordnername',\r\n NEW_FILE_CONFIRM: 'Erstellen',\r\n NEW_FILE_CANCEL: 'Abbrechen',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Keine Datei',\r\n COPY_TITLE: 'Editor-Inhalt kopieren',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Kopieren',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'Keine Γnderungen gegenΓΌber dem Original',\r\n NO_CHANGES_SHORT: 'Keine Γnderungen',\r\n LAUNCH_BTN: 'βΆ Test starten',\r\n LAUNCH_LOCAL_ONLY: 'Wechsle zu localhost, um Tests auszufΓΌhren',\r\n LAUNCH_RUNNING: 'β³ LΓ€uftβ¦',\r\n LAUNCH_PASSED: 'β Test bestanden',\r\n LAUNCH_FAILED: 'β Test fehlgeschlagen',\r\n LAUNCH_NO_RUNNER: 'Kein lokaler Runner erkannt (gestartet?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Speichern',\r\n CLOSE_BTN: 'β SchlieΓen',\r\n BACK_TO_EDITOR: 'β ZurΓΌck zum Editor',\r\n INSERT_BTN: 'πͺ BlΓΆcke einfΓΌgen',\r\n INSERT_TITLE: 'it() und beforeEach() in den Editor-Inhalt einfΓΌgen',\r\n INSERT_DONE: 'BlΓΆcke in den Editor eingefΓΌgt',\r\n INSERT_ERROR: 'Kein gΓΌltiger describe()-Block in der Datei gefunden',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Dateizugriff',\r\n FS_LATER_BTN: 'Nicht jetzt',\r\n FS_SELECT_BTN: 'π Ordner auswΓ€hlen',\r\n FS_SUCCESS_TOAST: 'β Cypress-Ordner konfiguriert',\r\n FS_ERROR_TOAST: 'Fehler beim Zugriff auf den Ordner',\r\n FS_INTRO_HTML: 'Der <strong style=\"color:#e6edf3\">erweiterte Editor</strong> kann Ihre Tests direkt in die Cypress-Dateien <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> einfΓΌgen.',\r\n FS_STRUCTURE_HINT_HTML: 'WΓ€hlen Sie den Ordner, der den Unterordner <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code> enthΓ€lt. Die Erweiterung erwartet diese Struktur:',\r\n FS_TREE_PICK_HINT: 'β diesen Ordner auswΓ€hlen',\r\n FS_TREE_READ_HINT: 'β die Erweiterung liest hier',\r\n FS_PERMISSION_NOTE: 'Die Berechtigung wird im Browser gespeichert und nicht erneut angefordert.',\r\n ASSERTION_SECTION: 'β Assertion hinzufΓΌgen',\r\n ASSERT_SELECTOR_PH: 'Selektor, z. B.: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'erwarteter Wert',\r\n ASSERT_ADD_BTN: 'β HinzufΓΌgen',\r\n FILE_EDITOR_TITLE: 'βοΈ Datei-Editor',\r\n FILE_SAVED_TOAST: 'β Datei gespeichert',\r\n FILE_SAVE_ERROR_TOAST: 'Fehler beim Speichern',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Dateien',\r\n BTN_COMMANDS: 'Befehle',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pausieren (Ctrl+P)',\r\n RESUME_TITLE: 'Fortsetzen (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSE',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Stopp (Ctrl+R)',\r\n START_TITLE: 'Aufzeichnen (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Aufzeichnung lΓ€uft',\r\n SESSION_RESUME_TEXT: 'Es gibt eine nicht abgeschlossene aktive Aufzeichnung.',\r\n SESSION_RESUME_COUNT: 'erfasste Befehle',\r\n SESSION_CONTINUE_BTN: 'Weiter aufzeichnen',\r\n SESSION_DISCARD_BTN: 'Verwerfen',\r\n },\r\n};\r\n","import { type Lang, isLang } from '../models/lang.model';\r\nimport { Subject } from '../utils/subject';\r\nimport { I18N_ES } from '../i18n/es';\r\nimport { I18N_EN } from '../i18n/en';\r\nimport { I18N_FR } from '../i18n/fr';\r\nimport { I18N_IT } from '../i18n/it';\r\nimport { I18N_DE } from '../i18n/de';\r\n\r\ntype Translations = typeof I18N_ES;\r\n\r\nexport class TranslationService {\r\n private readonly lang$: Subject<Lang>;\r\n\r\n private readonly translations: Record<Lang, Translations> = {\r\n es: I18N_ES,\r\n en: I18N_EN,\r\n fr: I18N_FR,\r\n it: I18N_IT,\r\n de: I18N_DE,\r\n };\r\n\r\n constructor() {\r\n this.lang$ = new Subject<Lang>(this.detectLang());\r\n }\r\n\r\n setLang(lang: Lang): void {\r\n this.lang$.next(lang);\r\n }\r\n\r\n getLang(): Lang {\r\n return this.lang$.getValue();\r\n }\r\n\r\n /** Subscribe to language changes; returns an unsubscribe function. */\r\n onLangChange(fn: (lang: Lang) => void): () => void {\r\n return this.lang$.subscribe(fn);\r\n }\r\n\r\n translate(key: string): string {\r\n const keys = key.split('.');\r\n let value: unknown = this.translations[this.lang$.getValue()];\r\n for (const k of keys) {\r\n value = (value as Record<string, unknown>)?.[k];\r\n if (value === undefined) return key;\r\n }\r\n return value as string;\r\n }\r\n\r\n detectLang(): Lang {\r\n const browserLang = navigator.language.split('-')[0];\r\n return isLang(browserLang) ? browserLang : 'es';\r\n }\r\n}\r\n\r\nexport const translationService = new TranslationService();\r\n","function gcd(a: number, b: number): number {\n while (b) { const t = b; b = a % b; a = t; }\n return a;\n}\n\n/**\n * Escapes backslashes and single quotes so a value can be safely embedded inside\n * a single-quoted JavaScript string literal β e.g. an `it('β¦')` / `describe('β¦')`\n * name. Without this, a test named `User's login` produces broken generated JS.\n */\nexport function escapeSingleQuotes(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Normalizes indentation in a code block and prefixes every line with baseIndent.\n *\n * Algorithm:\n * 1. Strip trailing whitespace from each line.\n * 2. Find the minimum leading-whitespace count of non-empty lines (dedent).\n * 3. Compute the indent step as the GCD of all non-zero relative indent values,\n * so the original indent unit (4-space, 8-space, etc.) maps to 2-space levels.\n * 4. Re-emit each line as: baseIndent + ' '.repeat(level) + trimmedContent.\n *\n * This handles multi-line interceptor/command blocks that were stored with\n * inconsistent or file-origin indentation.\n */\nexport function normalizeBlock(code: string, baseIndent: string): string {\n const lines = code.split('\\n').map(l => l.trimEnd());\n const nonEmpty = lines.filter(l => l.trim().length > 0);\n if (!nonEmpty.length) return '';\n\n const indents = nonEmpty.map(l => l.length - l.trimStart().length);\n const minIndent = Math.min(...indents);\n const relIndents = [...new Set(indents.map(n => n - minIndent).filter(n => n > 0))];\n const step = relIndents.length > 0 ? relIndents.reduce(gcd) : 2;\n\n return lines\n .map(l => {\n if (!l.trim()) return '';\n const level = Math.round((l.length - l.trimStart().length - minIndent) / step);\n return baseIndent + ' '.repeat(level) + l.trimStart();\n })\n .join('\\n');\n}\n","import { type Lang, isLang } from '../models/lang.model';\r\nimport { normalizeBlock, escapeSingleQuotes } from '../utils/code-format.utils';\r\n\r\nexport class TransformationService {\r\n toLang(lang: string): Lang {\r\n return isLang(lang) ? lang : 'en';\r\n }\r\n\r\n generateItDescription(description: string, commands: string[]): string {\r\n const commandsBlock = commands.map((cmd) => normalizeBlock(cmd, ' ')).join('\\n');\r\n return `it('${escapeSingleQuotes(description)}', () => {\\n${commandsBlock}\\n});`;\r\n }\r\n}\r\n\r\nexport const transformationService = new TransformationService();\r\n","export interface DirectoryNode {\r\n name: string;\r\n kind: 'directory';\r\n children: (DirectoryNode | FileNode)[];\r\n}\r\n\r\nexport interface FileNode {\r\n name: string;\r\n kind: 'file';\r\n}\r\n\r\nexport class AdvancedTestTransformationService {\r\n insertBeforeEach(content: string, interceptors: string, alertFn?: (msg: string) => void): string {\r\n const match = content.match(/(describe\\s*\\(.*?{)/s);\r\n if (!match) {\r\n alertFn?.('ADVANCED_EDITOR.NO_DESCRIBE');\r\n return '';\r\n }\r\n const insertPos = (match.index ?? 0) + match[0].length;\r\n const beforeEachBlock = `\\n beforeEach(() => {\\n${interceptors} })\\n`;\r\n return content.slice(0, insertPos) + beforeEachBlock + content.slice(insertPos);\r\n }\r\n\r\n insertItBlock(content: string, itBlock: string, alertFn?: (msg: string) => void): string {\r\n const idx = content.lastIndexOf('})');\r\n if (idx === -1) {\r\n alertFn?.('ADVANCED_EDITOR.NO_END');\r\n return '';\r\n }\r\n return content.slice(0, idx) + '\\n' + itBlock + '\\n' + content.slice(idx);\r\n }\r\n\r\n buildBlockComment(notes: string): string {\r\n if (!notes.trim()) return '';\r\n const lines = notes.split('\\n').map(l => ` * ${l}`).join('\\n');\r\n return `/**\\n${lines}\\n */`;\r\n }\r\n\r\n isFile(file: unknown): boolean {\r\n return !!file && (file as FileNode).kind === 'file';\r\n }\r\n\r\n async scanDirectory(dirHandle: FileSystemDirectoryHandle): Promise<DirectoryNode> {\r\n const result: DirectoryNode = { name: dirHandle.name, kind: 'directory', children: [] };\r\n for await (const entry of dirHandle.values()) {\r\n if (entry.kind === 'directory') {\r\n result.children.push(await this.scanDirectory(entry as FileSystemDirectoryHandle));\r\n } else {\r\n result.children.push({ name: entry.name, kind: 'file' });\r\n }\r\n }\r\n return result;\r\n }\r\n}\r\n\r\nexport const advancedTestTransformationService = new AdvancedTestTransformationService();\r\n","import { INPUT_TYPES } from '../models/input-types.model';\r\nimport type { ActiveSessionState } from '../models/active-session.model';\r\nimport { Subject } from '../utils/subject';\r\nimport { FORBIDDEN_ID_PREFIXES } from '../utils/selector-quality.utils';\r\n\r\nconst OWN_SELECTOR = '[data-cy=\"lib-e2e-cypress-for-dummys\"]';\r\n\r\nexport type SelectorStrategy = 'data-cy' | 'data-testid' | 'aria-label' | 'id';\r\n\r\n/** Generates a stable, collision-resistant session id (browser + jsdom safe). */\r\nfunction createSessionId(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n return `sess-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e9).toString(36)}`;\r\n}\r\n\r\nexport class RecordingService {\r\n private readonly commands$ = new Subject<string[]>([]);\r\n private readonly interceptors$ = new Subject<string[]>([]);\r\n private readonly isRecording$ = new Subject<boolean>(false);\r\n private readonly isPaused$ = new Subject<boolean>(false);\r\n private readonly selectorNotFound$ = new Subject<{ target: HTMLElement; action: 'click' } | null>(null);\r\n private readonly inputDebounceTimers = new Map<HTMLElement, ReturnType<typeof setTimeout>>();\r\n private readonly abort = new AbortController();\r\n\r\n selectorStrategy: SelectorStrategy = 'data-cy';\r\n\r\n /** Stable id of the current live session (null when none has started). */\r\n sessionId: string | null = null;\r\n private startedAt = 0;\r\n\r\n // Stored originals for history patching cleanup\r\n private readonly origPushState = history.pushState.bind(history);\r\n private readonly origReplaceState = history.replaceState.bind(history);\r\n\r\n constructor() {\r\n this.listenToClicks();\r\n this.listenToInput();\r\n this.listenToSelect();\r\n this.listenToRouteChanges();\r\n }\r\n\r\n // ββ Public API ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n startRecording(): void {\r\n this.sessionId = createSessionId();\r\n this.startedAt = Date.now();\r\n this.isPaused$.next(false);\r\n this.isRecording$.next(true);\r\n this.addCommand(`cy.viewport(1900, 1200)`);\r\n this.addCommand(`cy.visit('${window.location.pathname}')`);\r\n this.addCommand(`cy.get('[data-cy=\"lib-e2e-cypress-for-dummys\"]').invoke('hide');`);\r\n }\r\n\r\n /**\r\n * Rehydrates a previously persisted session WITHOUT running the startRecording\r\n * bootstrap (no viewport/visit/hide). Used to continue a recording across a\r\n * micro-frontend crossing or a same-origin reload.\r\n * See docs/specs/006-cross-app-recording-continuity.md.\r\n */\r\n restoreSession(state: ActiveSessionState): void {\r\n this.sessionId = state.sessionId;\r\n this.startedAt = state.startedAt;\r\n this.selectorStrategy = state.selectorStrategy;\r\n this.commands$.next([...state.commands]);\r\n this.interceptors$.next([...state.interceptors]);\r\n this.isPaused$.next(state.isPaused);\r\n // isRecording last so subscribers observe a fully-populated buffer.\r\n this.isRecording$.next(state.isRecording);\r\n }\r\n\r\n /** Full snapshot of the live session for persistence. */\r\n getSessionSnapshot(): ActiveSessionState {\r\n return {\r\n sessionId: this.sessionId ?? createSessionId(),\r\n isRecording: this.isRecording$.getValue(),\r\n isPaused: this.isPaused$.getValue(),\r\n commands: this.commands$.getValue(),\r\n interceptors: this.interceptors$.getValue(),\r\n selectorStrategy: this.selectorStrategy,\r\n startedAt: this.startedAt,\r\n updatedAt: Date.now(),\r\n };\r\n }\r\n\r\n stopRecording(): void {\r\n this.isPaused$.next(false);\r\n this.isRecording$.next(false);\r\n }\r\n\r\n toggleRecording(): void {\r\n if (this.isRecording$.getValue()) {\r\n this.stopRecording();\r\n } else {\r\n this.startRecording();\r\n }\r\n }\r\n\r\n pauseRecording(): void {\r\n if (!this.isRecording$.getValue()) return;\r\n this.isPaused$.next(true);\r\n }\r\n\r\n resumeRecording(): void {\r\n this.isPaused$.next(false);\r\n }\r\n\r\n togglePause(): void {\r\n if (this.isPaused$.getValue()) {\r\n this.resumeRecording();\r\n } else {\r\n this.pauseRecording();\r\n }\r\n }\r\n\r\n addCommand(cmd: string): void {\r\n if (!this.isRecording$.getValue() || this.isPaused$.getValue()) return;\r\n this.commands$.next([...this.commands$.getValue(), cmd]);\r\n }\r\n\r\n /** Appends a command regardless of recording/paused state (e.g. assertions added manually). */\r\n appendCommand(cmd: string): void {\r\n this.commands$.next([...this.commands$.getValue(), cmd]);\r\n }\r\n\r\n removeCommand(index: number): void {\r\n const cmds = this.commands$.getValue();\r\n if (index < 0 || index >= cmds.length) return;\r\n this.commands$.next([...cmds.slice(0, index), ...cmds.slice(index + 1)]);\r\n }\r\n\r\n moveCommand(from: number, to: number): void {\r\n const cmds = [...this.commands$.getValue()];\r\n if (from < 0 || to < 0 || from >= cmds.length || to >= cmds.length || from === to) return;\r\n const [item] = cmds.splice(from, 1);\r\n cmds.splice(to, 0, item);\r\n this.commands$.next(cmds);\r\n }\r\n\r\n removeInterceptor(index: number): void {\r\n const ints = this.interceptors$.getValue();\r\n if (index < 0 || index >= ints.length) return;\r\n this.interceptors$.next([...ints.slice(0, index), ...ints.slice(index + 1)]);\r\n }\r\n\r\n registerInterceptor(method: string, url: string, alias: string): void {\r\n if (this.isPaused$.getValue()) return;\r\n const command = `cy.intercept('${method}', '${this.urlToWildcard(url, method)}').as('${alias}')`;\r\n const current = this.interceptors$.getValue();\r\n if (!current.includes(command)) {\r\n this.interceptors$.next([...current, command]);\r\n }\r\n }\r\n\r\n clearCommands(): void {\r\n this.commands$.next([]);\r\n this.interceptors$.next([]);\r\n }\r\n\r\n clearInterceptors(): void {\r\n this.interceptors$.next([]);\r\n }\r\n\r\n getCommandsSnapshot(): string[] { return this.commands$.getValue(); }\r\n getInterceptorsSnapshot(): string[] { return this.interceptors$.getValue(); }\r\n getPausedSnapshot(): boolean { return this.isPaused$.getValue(); }\r\n\r\n onCommandsChange(fn: (cmds: string[]) => void): () => void {\r\n return this.commands$.subscribe(fn);\r\n }\r\n\r\n onInterceptorsChange(fn: (ints: string[]) => void): () => void {\r\n return this.interceptors$.subscribe(fn);\r\n }\r\n\r\n onRecordingChange(fn: (isRecording: boolean) => void): () => void {\r\n return this.isRecording$.subscribe(fn);\r\n }\r\n\r\n onPauseChange(fn: (isPaused: boolean) => void): () => void {\r\n return this.isPaused$.subscribe(fn);\r\n }\r\n\r\n /**\r\n * Fires a full session snapshot whenever any persisted field changes\r\n * (commands, interceptors, recording or paused state). Drives the debounced\r\n * persistence of the live session. Returns a combined unsubscribe.\r\n */\r\n onSessionChange(fn: (state: ActiveSessionState) => void): () => void {\r\n const emit = (): void => fn(this.getSessionSnapshot());\r\n const unsubs = [\r\n this.commands$.subscribe(emit),\r\n this.interceptors$.subscribe(emit),\r\n this.isRecording$.subscribe(emit),\r\n this.isPaused$.subscribe(emit),\r\n ];\r\n return () => unsubs.forEach((u) => u());\r\n }\r\n\r\n onSelectorNotFound(fn: (target: HTMLElement, action: 'click') => void): () => void {\r\n return this.selectorNotFound$.subscribe((v) => {\r\n if (v) fn(v.target, v.action);\r\n });\r\n }\r\n\r\n destroy(): void {\r\n this.abort.abort();\r\n history.pushState = this.origPushState;\r\n history.replaceState = this.origReplaceState;\r\n this.inputDebounceTimers.forEach((t) => clearTimeout(t));\r\n this.inputDebounceTimers.clear();\r\n }\r\n\r\n // ββ DOM listeners βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private listenToClicks(): void {\r\n document.addEventListener(\r\n 'click',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n const tag = target.tagName?.toLowerCase();\r\n if (tag === 'body' || tag === 'html') return;\r\n this.handleClickEvent(target);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToInput(): void {\r\n document.addEventListener(\r\n 'input',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLInputElement | HTMLTextAreaElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n this.handleInputEvent(target);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToSelect(): void {\r\n document.addEventListener(\r\n 'change',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLSelectElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n if (target.tagName.toLowerCase() === 'select') {\r\n this.handleSelectEvent(target);\r\n }\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToRouteChanges(): void {\r\n let lastUrl = window.location.pathname + window.location.search + window.location.hash;\r\n\r\n const addUrlCommand = (newUrl: string): void => {\r\n if (!this.isRecording$.getValue()) return;\r\n if (newUrl === lastUrl) return;\r\n this.addCommand(`cy.url().should('include', '${newUrl}')`);\r\n lastUrl = newUrl;\r\n };\r\n\r\n const wrapMethod = (type: 'pushState' | 'replaceState'): void => {\r\n const orig = history[type].bind(history);\r\n history[type] = (data: unknown, unused: string, url?: string | URL | null) => {\r\n const result = orig(data, unused, url);\r\n let newUrl = window.location.pathname + window.location.search + window.location.hash;\r\n if (typeof url === 'string' && url.length > 0) {\r\n const a = document.createElement('a');\r\n a.href = url;\r\n newUrl = a.pathname + a.search + a.hash;\r\n } else if (url instanceof URL) {\r\n newUrl = url.pathname + url.search + url.hash;\r\n }\r\n addUrlCommand(newUrl);\r\n return result;\r\n };\r\n };\r\n\r\n wrapMethod('pushState');\r\n wrapMethod('replaceState');\r\n\r\n window.addEventListener(\r\n 'popstate',\r\n () => {\r\n const newUrl = window.location.pathname + window.location.search + window.location.hash;\r\n addUrlCommand(newUrl);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n // ββ Click helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleClickEvent(target: HTMLElement): void {\r\n // Bubble up from non-interactive span/div inside button or mat-option\r\n if (!this.isInteractiveElement(target)) {\r\n const tag = target.tagName.toLowerCase();\r\n if (\r\n (tag === 'span' || tag === 'div') &&\r\n target.parentElement &&\r\n (target.parentElement.tagName.toLowerCase() === 'button' ||\r\n target.parentElement.tagName.toLowerCase() === 'mat-option') &&\r\n (target.parentElement.hasAttribute('data-cy') || target.parentElement.hasAttribute('id'))\r\n ) {\r\n target = target.parentElement;\r\n }\r\n const matSelect = target.closest('mat-select');\r\n if (matSelect) {\r\n const sel = this.getReliableSelector(matSelect as HTMLElement);\r\n if (sel) {\r\n this.addCommand(`cy.get('${sel}').click()`);\r\n } else {\r\n this.selectorNotFound$.next({ target: matSelect as HTMLElement, action: 'click' });\r\n }\r\n return;\r\n }\r\n }\r\n\r\n const tag = target.tagName.toLowerCase();\r\n if (tag === 'input' || tag === 'textarea' || tag === 'select') {\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) this.selectorNotFound$.next({ target, action: 'click' });\r\n return;\r\n }\r\n\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) {\r\n this.selectorNotFound$.next({ target, action: 'click' });\r\n return;\r\n }\r\n\r\n const selector = this.getReliableSelector(container);\r\n if (selector === OWN_SELECTOR) return;\r\n\r\n if (tag === 'mat-option') {\r\n this.handleMatOptionClick(target, selector);\r\n return;\r\n }\r\n\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').click()`,\r\n });\r\n }\r\n\r\n private handleMatOptionClick(target: HTMLElement, selector: string | null): void {\r\n const matSelect = target.closest('mat-select');\r\n let dataCy: string | null = null;\r\n if (matSelect) dataCy = matSelect.closest('[data-cy]')?.getAttribute('data-cy') ?? null;\r\n if (!dataCy) dataCy = target.closest('[data-cy]')?.getAttribute('data-cy') ?? null;\r\n if (dataCy) {\r\n this.addCommand(`cy.get('[data-cy=\"${dataCy}\"]').click()`);\r\n return;\r\n }\r\n if (selector) {\r\n this.addCommand(`cy.get('${selector}').eq(0).click()`);\r\n } else {\r\n this.selectorNotFound$.next({ target, action: 'click' });\r\n }\r\n }\r\n\r\n // ββ Input helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleInputEvent(target: HTMLInputElement | HTMLTextAreaElement): void {\r\n const tag = target.tagName.toLowerCase();\r\n const isText = tag === 'textarea' || (tag === 'input' && (INPUT_TYPES as readonly string[]).includes(target.type));\r\n if (!isText) return;\r\n\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) return;\r\n\r\n if (this.inputDebounceTimers.has(target)) {\r\n clearTimeout(this.inputDebounceTimers.get(target));\r\n }\r\n this.inputDebounceTimers.set(\r\n target,\r\n setTimeout(() => {\r\n const selector = this.getReliableSelector(container);\r\n const value = target.value.replace(/'/g, \"\\\\'\");\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').clear().type('${value}')`,\r\n });\r\n this.inputDebounceTimers.delete(target);\r\n }, 1000)\r\n );\r\n }\r\n\r\n // ββ Select helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleSelectEvent(target: HTMLSelectElement): void {\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) return;\r\n const selector = this.getReliableSelector(container);\r\n const value = target.value.replace(/'/g, \"\\\\'\");\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').select('${value}')`,\r\n });\r\n }\r\n\r\n // ββ Shared helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private addGenericCommand(opts: {\r\n selector: string | null;\r\n action: (s: string) => string;\r\n }): void {\r\n if (!opts.selector || this.isOwnSelector(opts.selector)) return;\r\n this.addCommand(opts.action(opts.selector));\r\n }\r\n\r\n private getReliableSelector(el: HTMLElement): string | null {\r\n const strategy = this.selectorStrategy;\r\n const dataCy = el.getAttribute('data-cy');\r\n const dataTestid = el.getAttribute('data-testid');\r\n const ariaLabel = el.getAttribute('aria-label');\r\n const dataDotCy = el.getAttribute('data.cy');\r\n\r\n const rawId = el.id;\r\n const validId = rawId &&\r\n rawId.length < 25 &&\r\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\r\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\r\n !/^\\d+$/.test(rawId) ? rawId : null;\r\n\r\n switch (strategy) {\r\n case 'data-testid':\r\n if (dataTestid) return `[data-testid=\"${dataTestid}\"]`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n case 'aria-label':\r\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n case 'id':\r\n if (validId) return `#${validId}`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return dataTestid ? `[data-testid=\"${dataTestid}\"]` : null;\r\n default: // 'data-cy'\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n if (dataDotCy) return `[data.cy=\"${dataDotCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n }\r\n }\r\n\r\n private isInteractiveElement(target: EventTarget | null): boolean {\r\n if (!(target instanceof HTMLElement)) return false;\r\n const tag = target.tagName.toLowerCase();\r\n return ['select', 'option', 'input', 'textarea', 'button'].includes(tag);\r\n }\r\n\r\n private isOwnSelector(selector: string | null): boolean {\r\n return selector === OWN_SELECTOR;\r\n }\r\n\r\n private isOwnElement(target: HTMLElement): boolean {\r\n return !!target.closest('[data-cy=\"lib-e2e-cypress-for-dummys\"]');\r\n }\r\n\r\n private urlToWildcard(url: string, method: string): string {\r\n const u = new URL(url, 'http://localhost');\r\n if (method.toUpperCase() === 'GET' && u.search) {\r\n return `**${u.pathname}/**`;\r\n }\r\n return `**${u.pathname}`;\r\n }\r\n}\r\n","import { openDB, type IDBPDatabase } from 'idb';\r\nimport { DB_SCHEMA } from '../models/db-schema.model';\r\nimport type { ActiveSessionState } from '../models/active-session.model';\r\nimport { normalizeBlock, escapeSingleQuotes } from '../utils/code-format.utils';\r\n\r\n/** Fixed primary key for the single active-session record. */\r\nconst ACTIVE_SESSION_ID = 1;\r\n\r\ninterface TestRecord { id: number; name: string; createdAt: number; tags?: string[]; notes?: string; }\r\ninterface CommandRecord { id: number; command: string; testId: number; createdAt: number; }\r\ninterface InterceptorRecord { id: number; interceptor: string; testId: number; createdAt: number; }\r\ninterface ConfigRecord { id: number; [key: string]: unknown; }\r\n\r\nexport interface TestWithDetails extends TestRecord {\r\n commands: string[];\r\n interceptors: string[];\r\n}\r\n\r\nexport interface TestDetail extends TestWithDetails {\r\n cypressCommands: string[];\r\n itBlock: string;\r\n interceptorsBlock: string;\r\n}\r\n\r\nexport class PersistenceService {\r\n private _db: Promise<IDBPDatabase> | null = null;\r\n\r\n // dbName is overridable so tests can use unique names for isolation.\r\n constructor(private readonly dbName: string = DB_SCHEMA.name) {}\r\n\r\n private getDB(): Promise<IDBPDatabase> {\r\n if (!this._db) {\r\n this._db = openDB(this.dbName, DB_SCHEMA.version, {\r\n upgrade(database) {\r\n for (const store of DB_SCHEMA.stores) {\r\n if (!database.objectStoreNames.contains(store.name)) {\r\n const os = database.createObjectStore(store.name, {\r\n keyPath: store.keyPath,\r\n autoIncrement: store.autoIncrement,\r\n });\r\n for (const index of store.indexes) {\r\n os.createIndex(index.name, index.keyPath, { unique: index.unique });\r\n }\r\n }\r\n }\r\n },\r\n });\r\n }\r\n return this._db;\r\n }\r\n\r\n // ββ Tests βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertTest(name: string, commands: string[] = [], interceptors: string[] = [], tags: string[] = [], notes?: string): Promise<number> {\r\n const db = await this.getDB();\r\n const record: Omit<TestRecord, 'id'> = { name, createdAt: Date.now(), ...(tags.length ? { tags } : {}), ...(notes ? { notes } : {}) };\r\n const id = await db.add('tests', record) as number;\r\n if (commands.length) await this.insertCommands(commands, id);\r\n if (interceptors.length) await this.insertInterceptors(interceptors, id);\r\n return id;\r\n }\r\n\r\n async getAllTests(): Promise<TestWithDetails[]> {\r\n const db = await this.getDB();\r\n const tests = await db.getAll('tests') as TestRecord[];\r\n return Promise.all(\r\n tests.map(async (test) => ({\r\n ...test,\r\n commands: await this.getCommandStrings(test.id),\r\n interceptors: await this.getInterceptorStrings(test.id),\r\n }))\r\n );\r\n }\r\n\r\n async getTestById(testId: number): Promise<TestDetail | null> {\r\n const db = await this.getDB();\r\n const record = await db.get('tests', testId) as TestRecord | undefined;\r\n if (!record) return null;\r\n\r\n const commands = await this.getCommandStrings(testId);\r\n const interceptors = await this.getInterceptorStrings(testId);\r\n const itBlock = `it('${escapeSingleQuotes(record.name)}', () => {\\n${commands.map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});`;\r\n const interceptorsBlock = interceptors.length\r\n ? ' // Auto-generated Cypress interceptors\\n' +\r\n interceptors.map(i => normalizeBlock(i, ' ')).join('\\n') + '\\n'\r\n : '';\r\n\r\n return { ...record, commands, interceptors, cypressCommands: commands, itBlock, interceptorsBlock };\r\n }\r\n\r\n async deleteTest(id: number): Promise<void> {\r\n const db = await this.getDB();\r\n await db.delete('tests', id);\r\n await this.deleteCommandsByTestId(id);\r\n await this.deleteInterceptorsByTestId(id);\r\n }\r\n\r\n // ββ Commands ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertCommands(commands: string[], testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all(\r\n commands.map((command) => db.add('commands', { command, testId, createdAt: Date.now() }))\r\n );\r\n }\r\n\r\n async getCommandsByTestId(testId: number): Promise<CommandRecord[]> {\r\n const db = await this.getDB();\r\n return db.getAllFromIndex('commands', 'testId', testId) as Promise<CommandRecord[]>;\r\n }\r\n\r\n private async getCommandStrings(testId: number): Promise<string[]> {\r\n return (await this.getCommandsByTestId(testId)).map((r) => r.command).filter(Boolean);\r\n }\r\n\r\n private async deleteCommandsByTestId(testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n const rows = await this.getCommandsByTestId(testId);\r\n const tx = db.transaction('commands', 'readwrite');\r\n await Promise.all(rows.map((r) => tx.store.delete(r.id)));\r\n await tx.done;\r\n }\r\n\r\n // ββ Interceptors ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertInterceptors(interceptors: string[], testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all(\r\n interceptors.map((interceptor) => db.add('interceptors', { interceptor, testId, createdAt: Date.now() }))\r\n );\r\n }\r\n\r\n async getInterceptorsByTestId(testId: number): Promise<InterceptorRecord[]> {\r\n const db = await this.getDB();\r\n return db.getAllFromIndex('interceptors', 'testId', testId) as Promise<InterceptorRecord[]>;\r\n }\r\n\r\n private async getInterceptorStrings(testId: number): Promise<string[]> {\r\n return (await this.getInterceptorsByTestId(testId)).map((r) => r.interceptor).filter(Boolean);\r\n }\r\n\r\n async deleteInterceptorsByTestId(testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n const rows = await this.getInterceptorsByTestId(testId);\r\n const tx = db.transaction('interceptors', 'readwrite');\r\n await Promise.all(rows.map((r) => tx.store.delete(r.id)));\r\n await tx.done;\r\n }\r\n\r\n // ββ Configuration βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async setConfig(config: Record<string, unknown>): Promise<void> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n const current = records[0] ?? {};\r\n const merged = { ...current, ...config };\r\n if ((current as ConfigRecord).id) {\r\n await db.put('configuration', merged);\r\n } else {\r\n await db.add('configuration', merged);\r\n }\r\n }\r\n\r\n async setConfigKey(key: string, value: unknown): Promise<void> {\r\n return this.setConfig({ [key]: value });\r\n }\r\n\r\n async getConfig(key: string): Promise<Record<string, unknown> | null> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n if (!records.length) return null;\r\n const config = records[0];\r\n return Object.prototype.hasOwnProperty.call(config, key) ? { [key]: config[key] } : null;\r\n }\r\n\r\n async getGeneralConfig(): Promise<ConfigRecord | null> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n return records[0] ?? null;\r\n }\r\n\r\n // ββ Active recording session ββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n /** Upserts the live recording session (single record, fixed key). */\r\n async saveActiveSession(state: ActiveSessionState): Promise<void> {\r\n const db = await this.getDB();\r\n await db.put('activeSession', { ...state, id: ACTIVE_SESSION_ID });\r\n }\r\n\r\n /** Returns the persisted live session, or null when none is stored. */\r\n async getActiveSession(): Promise<ActiveSessionState | null> {\r\n const db = await this.getDB();\r\n const record = await db.get('activeSession', ACTIVE_SESSION_ID) as (ActiveSessionState & { id: number }) | undefined;\r\n if (!record) return null;\r\n const { id: _id, ...state } = record;\r\n return state as ActiveSessionState;\r\n }\r\n\r\n /** Removes the live session record. Safe to call when none exists. */\r\n async clearActiveSession(): Promise<void> {\r\n const db = await this.getDB();\r\n await db.delete('activeSession', ACTIVE_SESSION_ID);\r\n }\r\n\r\n // ββ Bulk operations βββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async clearAllData(): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all([\r\n db.clear('tests'),\r\n db.clear('commands'),\r\n db.clear('interceptors'),\r\n ]);\r\n }\r\n\r\n async ingestFileData(tests: Record<string, unknown>[], interceptors: Record<string, unknown>[]): Promise<void> {\r\n if (Array.isArray(tests)) {\r\n const db = await this.getDB();\r\n for (const test of tests) {\r\n // Split the nested commands/interceptors back into their own stores,\r\n // keyed by the freshly-assigned testId β otherwise they would be stored\r\n // as stray fields and silently lost on read (getAllTests reads them by\r\n // testId from the commands/interceptors stores).\r\n const { id: _id, commands, interceptors: testInterceptors, ...record } = test;\r\n const newId = await db.add('tests', record) as number;\r\n const cmds = Array.isArray(commands) ? commands as string[] : [];\r\n const icps = Array.isArray(testInterceptors) ? testInterceptors as string[] : [];\r\n if (cmds.length) await this.insertCommands(cmds, newId);\r\n if (icps.length) await this.insertInterceptors(icps, newId);\r\n }\r\n }\r\n // Back-compat: legacy files may carry top-level interceptors with their own testId.\r\n await this.bulkInsertWithoutId('interceptors', interceptors);\r\n }\r\n\r\n async requestDirectoryPermissions(): Promise<void> {\r\n if (!('showDirectoryPicker' in window)) {\r\n throw new Error('File System Access API not supported');\r\n }\r\n const dirHandle = await window.showDirectoryPicker();\r\n await this.setConfigKey('cypressDirectoryHandle', dirHandle);\r\n await this.setConfigKey('allowReadWriteFiles', 'true');\r\n }\r\n\r\n private async bulkInsertWithoutId(store: string, items: Record<string, unknown>[]): Promise<void> {\r\n if (!Array.isArray(items)) return;\r\n const db = await this.getDB();\r\n for (const item of items) {\r\n const { id: _id, ...rest } = item;\r\n await db.add(store, rest);\r\n }\r\n }\r\n}\r\n\r\nexport const persistenceService = new PersistenceService();\r\n","import { type RecordingService } from './recording.service';\r\n\r\nconst INTERCEPTED_METHODS = ['GET', 'POST', 'PUT'] as const;\r\ntype InterceptedMethod = (typeof INTERCEPTED_METHODS)[number];\r\n\r\nexport function generateAlias(method: string, url: string): string {\r\n try {\r\n const u = new URL(url, 'http://localhost');\r\n const path = u.pathname\r\n .replace(/[^a-zA-Z0-9]/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/(^-)|(-$)/g, '');\r\n return `${method.toLowerCase()}-${path}`;\r\n } catch {\r\n return `${method.toLowerCase()}-intercepted-request`;\r\n }\r\n}\r\n\r\nfunction buildValidations(base: string, obj: Record<string, unknown>): string {\r\n return Object.keys(obj)\r\n .filter((key) => key !== 'id' && key !== 'uid')\r\n .map((key) => `expect(${base}.${key}).to.equal(${JSON.stringify(obj[key])});`)\r\n .join('\\n');\r\n}\r\n\r\nfunction buildCyWaitCommand(\r\n method: string,\r\n alias: string,\r\n extendedHttp: boolean,\r\n requestBody: Record<string, unknown> | null,\r\n responseBody: Record<string, unknown> | null\r\n): string {\r\n if (extendedHttp && method === 'GET' && responseBody) {\r\n const validations = buildValidations('interception.response.body', responseBody);\r\n return `cy.wait('@${alias}').then((interception) => {\\n if (interception.response) {\\n${validations}\\n }\\n})`;\r\n }\r\n if (extendedHttp && (method === 'POST' || method === 'PUT') && requestBody) {\r\n const validations = buildValidations('interception.request.body', requestBody);\r\n return `cy.wait('@${alias}').then((interception) => {\\n${validations}\\n})`;\r\n }\r\n return `cy.wait('@${alias}').then((interception) => { })`;\r\n}\r\n\r\nfunction parseJsonObject(text: string): Record<string, unknown> | null {\r\n try {\r\n const parsed = JSON.parse(text);\r\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\r\n return parsed as Record<string, unknown>;\r\n }\r\n } catch {\r\n // Non-JSON or array β fall through\r\n }\r\n return null;\r\n}\r\n\r\nfunction parseRequestBody(init?: RequestInit): Record<string, unknown> | null {\r\n const body = init?.body;\r\n if (typeof body === 'string') return parseJsonObject(body);\r\n return null;\r\n}\r\n\r\nfunction resolveUrl(input: RequestInfo | URL): string {\r\n if (typeof input === 'string') return input;\r\n if (input instanceof URL) return input.href;\r\n return input.url;\r\n}\r\n\r\nfunction resolveMethod(input: RequestInfo | URL, init?: RequestInit): string {\r\n if (init?.method) return init.method.toUpperCase();\r\n if (input instanceof Request) return input.method.toUpperCase();\r\n return 'GET';\r\n}\r\n\r\nexport class HttpMonitor {\r\n private originalFetch: typeof window.fetch | null = null;\r\n private originalXHR: typeof XMLHttpRequest | null = null;\r\n\r\n constructor(private readonly recording: RecordingService) {}\r\n\r\n install(): void {\r\n this.installFetch();\r\n this.installXhr();\r\n }\r\n\r\n uninstall(): void {\r\n this.uninstallFetch();\r\n this.uninstallXhr();\r\n }\r\n\r\n isExtendedHttpEnabled(): boolean {\r\n return localStorage.getItem('extendedHttpCommands') === 'true';\r\n }\r\n\r\n private installFetch(): void {\r\n if (this.originalFetch) return;\r\n const originalFetch = window.fetch;\r\n this.originalFetch = originalFetch;\r\n\r\n window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\r\n const response = await originalFetch(input, init);\r\n try {\r\n await this.handleFetchInterception(input, init, response.clone());\r\n } catch {\r\n // Never let monitoring errors break the actual request\r\n }\r\n return response;\r\n };\r\n }\r\n\r\n private uninstallFetch(): void {\r\n if (!this.originalFetch) return;\r\n window.fetch = this.originalFetch;\r\n this.originalFetch = null;\r\n }\r\n\r\n private installXhr(): void {\r\n if (this.originalXHR) return;\r\n this.originalXHR = window.XMLHttpRequest;\r\n const OrigXHR = this.originalXHR;\r\n const handleXhrInterception = this.handleXhrInterception.bind(this);\r\n\r\n window.XMLHttpRequest = class extends OrigXHR {\r\n private _xhrMethod = 'GET';\r\n private _xhrUrl = '';\r\n private _xhrRequestBody: Record<string, unknown> | null = null;\r\n\r\n override open(\r\n method: string,\r\n url: string | URL,\r\n async = true,\r\n user?: string | null,\r\n password?: string | null\r\n ): void {\r\n this._xhrMethod = method.toUpperCase();\r\n this._xhrUrl = url instanceof URL ? url.href : url;\r\n super.open(method, url as string, async, user, password);\r\n }\r\n\r\n override send(body?: Document | XMLHttpRequestBodyInit | null): void {\r\n if (typeof body === 'string') {\r\n this._xhrRequestBody = parseJsonObject(body);\r\n }\r\n this.addEventListener('load', () => {\r\n try {\r\n handleXhrInterception(\r\n this._xhrMethod,\r\n this._xhrUrl,\r\n this._xhrRequestBody,\r\n this.responseText\r\n );\r\n } catch {\r\n // Never let monitoring errors surface\r\n }\r\n });\r\n super.send(body);\r\n }\r\n } as unknown as typeof XMLHttpRequest;\r\n }\r\n\r\n private uninstallXhr(): void {\r\n if (!this.originalXHR) return;\r\n window.XMLHttpRequest = this.originalXHR;\r\n this.originalXHR = null;\r\n }\r\n\r\n private async handleFetchInterception(\r\n input: RequestInfo | URL,\r\n init: RequestInit | undefined,\r\n responseClone: Response\r\n ): Promise<void> {\r\n const method = resolveMethod(input, init);\r\n if (!(INTERCEPTED_METHODS as readonly string[]).includes(method)) return;\r\n\r\n const url = resolveUrl(input);\r\n const alias = generateAlias(method, url);\r\n\r\n this.recording.registerInterceptor(method, url, alias);\r\n\r\n const extendedHttp = this.isExtendedHttpEnabled();\r\n const requestBody = extendedHttp ? parseRequestBody(init) : null;\r\n let responseBody: Record<string, unknown> | null = null;\r\n if (extendedHttp) {\r\n try {\r\n responseBody = parseJsonObject(await responseClone.text());\r\n } catch {\r\n // Unreadable body β continue without validations\r\n }\r\n }\r\n\r\n const cmd = buildCyWaitCommand(method, alias, extendedHttp, requestBody, responseBody);\r\n this.recording.addCommand(cmd);\r\n }\r\n\r\n private handleXhrInterception(\r\n method: string,\r\n url: string,\r\n requestBody: Record<string, unknown> | null,\r\n responseText: string\r\n ): void {\r\n if (!(INTERCEPTED_METHODS as readonly string[]).includes(method as InterceptedMethod)) return;\r\n\r\n const alias = generateAlias(method, url);\r\n this.recording.registerInterceptor(method, url, alias);\r\n\r\n const extendedHttp = this.isExtendedHttpEnabled();\r\n const responseBody = extendedHttp ? parseJsonObject(responseText) : null;\r\n\r\n const cmd = buildCyWaitCommand(method, alias, extendedHttp, requestBody, responseBody);\r\n this.recording.addCommand(cmd);\r\n }\r\n}\r\n\r\n","export const SCROLLBAR_STYLES = `\r\n.swal2-popup::-webkit-scrollbar,\r\n.swal2-html-container::-webkit-scrollbar,\r\n.swal2-content::-webkit-scrollbar,\r\n.swal2-container::-webkit-scrollbar {\r\n width: 5px;\r\n height: 5px;\r\n background: transparent;\r\n}\r\n.swal2-popup::-webkit-scrollbar-thumb,\r\n.swal2-html-container::-webkit-scrollbar-thumb,\r\n.swal2-content::-webkit-scrollbar-thumb,\r\n.swal2-container::-webkit-scrollbar-thumb {\r\n background: #30363d;\r\n border-radius: 3px;\r\n}\r\n.swal2-popup::-webkit-scrollbar-thumb:hover,\r\n.swal2-html-container::-webkit-scrollbar-thumb:hover,\r\n.swal2-content::-webkit-scrollbar-thumb:hover {\r\n background: #484f58;\r\n}\r\n.swal2-popup::-webkit-scrollbar-track,\r\n.swal2-html-container::-webkit-scrollbar-track,\r\n.swal2-content::-webkit-scrollbar-track,\r\n.swal2-container::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n.swal2-popup, .swal2-html-container, .swal2-content, .swal2-container {\r\n scrollbar-width: thin;\r\n scrollbar-color: #30363d transparent;\r\n}\r\n`;\r\n\r\nexport const LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES = `\r\n.swal2-container, .swal2-popup {\r\n z-index: 99999 !important;\r\n}\r\n.swal2-container {\r\n padding: 0 !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n}\r\n.swal2-popup {\r\n background: #161b22 !important;\r\n color: #e6edf3 !important;\r\n border-radius: 12px !important;\r\n box-shadow: 0 24px 64px rgba(0,0,0,0.72), 0 0 0 1px #30363d !important;\r\n border: none !important;\r\n padding: 0 !important;\r\n min-width: 400px;\r\n max-width: 90vw;\r\n min-height: 200px;\r\n max-height: 90vh;\r\n}\r\n/* Override SweetAlert2 v11's display:grid on .swal2-popup.swal2-modal */\r\n.swal2-popup.swal2-modal {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n align-items: stretch !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-header {\r\n flex-shrink: 0 !important;\r\n flex-grow: 0 !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-title {\r\n color: #e6edf3 !important;\r\n font-weight: 600 !important;\r\n font-size: 14px !important;\r\n background: #161b22;\r\n padding: 14px 48px 13px 18px !important;\r\n margin: 0 !important;\r\n border-bottom: 1px solid #21262d;\r\n text-align: left !important;\r\n letter-spacing: 0.1px;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n}\r\n.swal2-close {\r\n position: absolute !important;\r\n top: 10px !important;\r\n right: 12px !important;\r\n color: #8b949e !important;\r\n font-size: 1.1rem !important;\r\n z-index: 1 !important;\r\n border-radius: 6px !important;\r\n width: 28px !important;\r\n height: 28px !important;\r\n line-height: 28px !important;\r\n transition: background 0.15s, color 0.15s !important;\r\n}\r\n.swal2-close:hover {\r\n background: #21262d !important;\r\n color: #e6edf3 !important;\r\n}\r\n/* In SweetAlert2 v11, .swal2-html-container is a direct child of .swal2-popup */\r\n.swal2-html-container {\r\n flex: 1 !important;\r\n min-height: 0 !important;\r\n background: #161b22;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n width: 100%;\r\n display: flex !important;\r\n flex-direction: column !important;\r\n align-items: stretch;\r\n box-sizing: border-box;\r\n overflow: hidden !important;\r\n}\r\n/* The single wrapper div we inject inside each modal fills the container */\r\n.swal2-html-container > div {\r\n flex: 1 !important;\r\n min-height: 0 !important;\r\n display: flex !important;\r\n flex-direction: column !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-actions, .swal2-footer {\r\n flex-shrink: 0 !important;\r\n flex-grow: 0 !important;\r\n}\r\n`;\r\n\r\nexport function injectStyles(css: string, id: string): void {\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement('style');\r\n style.id = id;\r\n style.innerHTML = css;\r\n document.head.appendChild(style);\r\n}\r\n","export function makeModalResizable(\r\n modal: HTMLElement,\r\n options?: { minWidth?: number; minHeight?: number }\r\n): () => void {\r\n if (!modal || modal.querySelector('.modal-resizer')) return () => { /* no-op */ };\r\n\r\n const rect = modal.getBoundingClientRect();\r\n modal.style.position = 'fixed';\r\n modal.style.top = `${rect.top}px`;\r\n modal.style.left = `${rect.left}px`;\r\n modal.style.width = `${rect.width}px`;\r\n modal.style.margin = '0';\r\n modal.style.resize = 'both';\r\n modal.style.overflow = 'hidden';\r\n modal.style.minWidth = (options?.minWidth ?? 320) + 'px';\r\n modal.style.minHeight = (options?.minHeight ?? 180) + 'px';\r\n\r\n const resizer = document.createElement('div');\r\n resizer.className = 'modal-resizer';\r\n resizer.style.position = 'absolute';\r\n resizer.style.width = '16px';\r\n resizer.style.height = '16px';\r\n resizer.style.right = '2px';\r\n resizer.style.bottom = '2px';\r\n resizer.style.cursor = 'nwse-resize';\r\n resizer.style.background = 'rgba(0,0,0,0.1)';\r\n resizer.style.zIndex = '10';\r\n modal.appendChild(resizer);\r\n\r\n let isResizing = false;\r\n let lastX = 0;\r\n let lastY = 0;\r\n\r\n const mouseMove = (e: MouseEvent): void => {\r\n if (!isResizing) return;\r\n const dx = e.clientX - lastX;\r\n const dy = e.clientY - lastY;\r\n lastX = e.clientX;\r\n lastY = e.clientY;\r\n const rect = modal.getBoundingClientRect();\r\n modal.style.width = rect.width + dx + 'px';\r\n modal.style.height = rect.height + dy + 'px';\r\n };\r\n\r\n const mouseUp = (): void => {\r\n isResizing = false;\r\n document.body.style.userSelect = '';\r\n };\r\n\r\n resizer.addEventListener('mousedown', (e) => {\r\n e.preventDefault();\r\n isResizing = true;\r\n lastX = e.clientX;\r\n lastY = e.clientY;\r\n document.body.style.userSelect = 'none';\r\n });\r\n\r\n window.addEventListener('mousemove', mouseMove);\r\n window.addEventListener('mouseup', mouseUp);\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', mouseMove);\r\n window.removeEventListener('mouseup', mouseUp);\r\n if (resizer.parentNode) resizer.parentNode.removeChild(resizer);\r\n };\r\n}\r\n\r\nfunction applyDraggable(swal: HTMLElement, dragArea: HTMLElement): void {\r\n let isDragging = false;\r\n let offsetX = 0;\r\n let offsetY = 0;\r\n\r\n dragArea.style.cursor = 'move';\r\n dragArea.onmousedown = (e: MouseEvent) => {\r\n isDragging = true;\r\n const rect = swal.getBoundingClientRect();\r\n offsetX = e.clientX - rect.left;\r\n offsetY = e.clientY - rect.top;\r\n document.onmousemove = (ev: MouseEvent) => {\r\n if (isDragging) {\r\n swal.style.position = 'fixed';\r\n swal.style.margin = '0';\r\n swal.style.left = `${ev.clientX - offsetX}px`;\r\n swal.style.top = `${ev.clientY - offsetY}px`;\r\n }\r\n };\r\n document.onmouseup = () => {\r\n isDragging = false;\r\n document.onmousemove = null;\r\n document.onmouseup = null;\r\n };\r\n };\r\n}\r\n\r\nfunction resolveDragArea(swal: HTMLElement): HTMLElement | null {\r\n return (swal.querySelector('.swal2-header') as HTMLElement | null)\r\n ?? (swal.querySelector('.swal2-title') as HTMLElement | null);\r\n}\r\n\r\nexport function makeSwalDraggable(): void {\r\n const popups = document.querySelectorAll('.swal2-popup');\r\n if (!popups.length) return;\r\n const swal = popups[popups.length - 1] as HTMLElement;\r\n const dragArea = resolveDragArea(swal);\r\n if (!dragArea) return;\r\n applyDraggable(swal, dragArea);\r\n}\r\n\r\nexport function makeSwalDraggableByContentId(contentId: string): void {\r\n const content = document.getElementById(contentId);\r\n if (!content) {\r\n makeSwalDraggable();\r\n return;\r\n }\r\n const swal = (content.closest('.swal2-popup') as HTMLElement | null)\r\n ?? (document.querySelector('.swal2-popup') as HTMLElement | null);\r\n if (!swal) return;\r\n const dragArea = resolveDragArea(swal);\r\n if (!dragArea) return;\r\n applyDraggable(swal, dragArea);\r\n}\r\n\r\nexport function setSwal2DataCyAttribute(dataCy = 'lib-e2e-cypress-for-dummys'): void {\r\n document.querySelector('.swal2-container')?.setAttribute('data-cy', dataCy);\r\n document.querySelector('.swal2-html-container')?.setAttribute('data-cy', dataCy);\r\n document.querySelector('.swal2-title')?.setAttribute('data-cy', dataCy);\r\n}\r\n","export function showToast(message: string, isSuccess = true): void {\r\n const toast = document.createElement('div');\r\n toast.textContent = message;\r\n toast.style.position = 'fixed';\r\n toast.style.top = '30px';\r\n toast.style.right = '30px';\r\n toast.style.padding = '16px 24px';\r\n toast.style.background = isSuccess ? '#4caf50' : '#f44336';\r\n toast.style.color = '#fff';\r\n toast.style.borderRadius = '8px';\r\n toast.style.boxShadow = '0 2px 8px rgba(0,0,0,0.2)';\r\n toast.style.zIndex = '9999';\r\n toast.style.fontSize = '1rem';\r\n toast.style.fontWeight = 'bold';\r\n toast.style.pointerEvents = 'none';\r\n document.body.appendChild(toast);\r\n setTimeout(() => toast.remove(), 3000);\r\n}\r\n","import type { TestWithDetails } from '../services/persistence.service';\n\n/** How the user chose which tests to export. */\nexport type ExportMode = 'all' | 'manual' | 'tags';\n\nexport interface ExportSelectionOptions {\n /** Test ids to include in `manual` mode. */\n ids?: Iterable<number>;\n /** Tags to match in `tags` mode. */\n tags?: Iterable<string>;\n}\n\n/**\n * Returns the subset of tests to export for a given selection mode.\n *\n * - `all` β every test (a shallow copy).\n * - `manual` β tests whose id is in `opts.ids`. Empty/absent ids β none.\n * - `tags` β tests carrying at least one of `opts.tags` (OR semantics).\n * Empty/absent tags β none.\n *\n * Pure: never mutates its inputs.\n */\nexport function selectTestsForExport(\n tests: TestWithDetails[],\n mode: ExportMode,\n opts: ExportSelectionOptions = {},\n): TestWithDetails[] {\n if (mode === 'all') return [...tests];\n\n if (mode === 'manual') {\n const ids = new Set(opts.ids ?? []);\n return tests.filter((t) => ids.has(t.id));\n }\n\n // 'tags' β include a test if it carries ANY of the selected tags (OR).\n const tags = new Set(opts.tags ?? []);\n if (tags.size === 0) return [];\n return tests.filter((t) => (t.tags ?? []).some((tag) => tags.has(tag)));\n}\n","/**\n * True when a hostname refers to the local machine β used to gate dev-only\n * features (e.g. launching a Cypress run via the local runner) so they are\n * offered only when the app is served locally, not from a deployed environment.\n *\n * Treats as local: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, and the\n * empty hostname (e.g. file:// URLs). Case-insensitive.\n */\nexport function isLocalHost(hostname: string): boolean {\n if (!hostname) return true;\n const h = hostname.toLowerCase();\n return (\n h === 'localhost' ||\n h.endsWith('.localhost') ||\n h === '127.0.0.1' ||\n h === '::1' ||\n h === '0.0.0.0'\n );\n}\n","export const TEST_PREVISUALIZER_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .toolbar {\n display: flex; gap: 6px; padding: 10px 12px; flex-shrink: 0;\n background: #161b22; border-bottom: 1px solid #21262d;\n }\n button {\n padding: 5px 12px; border: none; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s; letter-spacing: 0.1px;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n button.active { background: #2f81f7; color: #fff; }\n .section { padding: 10px 12px; flex-shrink: 0; }\n .section.section-cmds { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .section-title {\n font-size: 10px; font-weight: 600; color: #484f58; text-transform: uppercase;\n letter-spacing: 0.8px; margin-bottom: 7px; flex-shrink: 0;\n }\n .list {\n overflow-y: auto; background: #0d1117;\n border-radius: 8px; padding: 6px 8px;\n border: 1px solid #21262d;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .section-cmds .list { flex: 1; min-height: 0; }\n .list::-webkit-scrollbar { width: 4px; }\n .list::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .item {\n display: flex; align-items: flex-start; gap: 6px;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 11px;\n color: #c9d1d9; padding: 4px 8px; border-radius: 4px;\n word-break: break-all; line-height: 1.65;\n border-left: 2px solid transparent;\n transition: background 0.1s, border-color 0.1s;\n }\n .item:hover { background: #161b22; border-left-color: #2f81f7; }\n .cmd-text { flex: 1; }\n .item-actions {\n display: flex; gap: 3px; flex-shrink: 0;\n opacity: 0; transition: opacity 0.15s;\n }\n .item:hover .item-actions { opacity: 1; }\n .btn-step {\n width: 20px; height: 20px; border: none; border-radius: 3px; cursor: pointer;\n font-size: 12px; background: transparent; color: #484f58;\n transition: background 0.12s, color 0.12s;\n display: flex; align-items: center; justify-content: center;\n padding: 0; line-height: 1;\n }\n .btn-step:hover { background: #30363d; color: #e6edf3; }\n .btn-step-del:hover { background: rgba(248,81,73,0.15); color: #f85149; }\n .empty { color: #484f58; font-size: 12px; padding: 20px 8px; text-align: center; }\n`;\n","import { escHtml } from '../../utils/html.utils';\n\nexport function renderTestPrevisualizer(\n commands: string[],\n interceptors: string[],\n showInterceptors: boolean,\n editable: boolean,\n t: (key: string) => string,\n): string {\n const editControls = (idx: number, total: number) => editable ? `\n <span class=\"item-actions\">\n <button class=\"btn-step\" data-move-up=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.UP_TITLE')}\" ${idx === 0 ? 'disabled style=\"opacity:.3\"' : ''}>β</button>\n <button class=\"btn-step\" data-move-dn=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DOWN_TITLE')}\" ${idx === total - 1 ? 'disabled style=\"opacity:.3\"' : ''}>β</button>\n <button class=\"btn-step btn-step-del\" data-del=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DEL_TITLE')}\">β</button>\n </span>` : '';\n\n const cmdItems = commands.length\n ? commands.map((c, i) => `\n <div class=\"item\">\n <span class=\"cmd-text\">${escHtml(c)}</span>\n ${editControls(i, commands.length)}\n </div>`).join('')\n : `<div class=\"empty\">${t('TEST_PREVISUALIZER.NO_CMDS_YET')}</div>`;\n\n const icpEditControls = (idx: number) => editable\n ? `<span class=\"item-actions\"><button class=\"btn-step btn-step-del\" data-del-icp=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DEL_TITLE')}\">β</button></span>`\n : '';\n\n const icpSection = showInterceptors\n ? `<div class=\"section\" data-section=\"interceptors\">\n <div class=\"section-title\">${t('TEST_PREVISUALIZER.INTERCEPTORS')}</div>\n <div class=\"list\">\n ${\n interceptors.length\n ? interceptors.map((ic, idx) => `\n <div class=\"item\">\n <span class=\"cmd-text\">${escHtml(ic)}</span>\n ${icpEditControls(idx)}\n </div>`).join('')\n : `<div class=\"empty\">${t('TEST_PREVISUALIZER.NO_ICP_SHORT')}</div>`\n }\n </div>\n <button style=\"margin-top:6px\" data-action=\"copy-icp\">${t('TEST_PREVISUALIZER.COPY_ICP_BTN')}</button>\n </div>`\n : '';\n\n return `\n <div class=\"toolbar\">\n <button data-action=\"copy\">${t('TEST_PREVISUALIZER.COPY_CMDS_BTN')}</button>\n <button data-action=\"toggle-icp\" class=\"${showInterceptors ? 'active' : ''}\">\n ${showInterceptors ? t('TEST_PREVISUALIZER.HIDE_INTERCEPTORS') : t('TEST_PREVISUALIZER.SHOW_INTERCEPTORS')} (${interceptors.length})\n </button>\n </div>\n <div class=\"section section-cmds\">\n <div class=\"section-title\">${t('TEST_PREVISUALIZER.SECTION_COMMANDS')} (${commands.length})</div>\n <div class=\"list\" data-ref=\"cmds\">${cmdItems}</div>\n </div>\n ${icpSection}`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { TEST_PREVISUALIZER_STYLES } from './test-previsualizer.styles';\r\nimport { renderTestPrevisualizer } from './test-previsualizer.template';\r\n\r\nexport class TestPrevisualizerElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private _commands: string[] = [];\r\n private _interceptors: string[] = [];\r\n private _showInterceptors = false;\r\n editable = false;\r\n translation: TranslationService = translationService;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n this.render();\r\n }\r\n\r\n get commands(): string[] {\r\n return this._commands;\r\n }\r\n set commands(v: string[]) {\r\n this._commands = v;\r\n this.render();\r\n }\r\n\r\n get interceptors(): string[] {\r\n return this._interceptors;\r\n }\r\n set interceptors(v: string[]) {\r\n this._interceptors = v;\r\n this.render();\r\n }\r\n\r\n get showInterceptors(): boolean {\r\n return this._showInterceptors;\r\n }\r\n\r\n toggleInterceptors(): void {\r\n this._showInterceptors = !this._showInterceptors;\r\n this.render();\r\n }\r\n\r\n copyToClipboard(): void {\r\n const text = this._commands.join('\\n');\r\n if (!text) return;\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n copyInterceptorsToClipboard(): void {\r\n const text = this._interceptors.join('\\n');\r\n if (!text) return;\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private dispatchDelete(index: number): void {\r\n this.dispatchEvent(new CustomEvent('deletecommand', { detail: index, bubbles: true, composed: true }));\r\n }\r\n\r\n private dispatchMove(from: number, to: number): void {\r\n this.dispatchEvent(new CustomEvent('movecommand', { detail: { from, to }, bubbles: true, composed: true }));\r\n }\r\n\r\n private dispatchDeleteInterceptor(index: number): void {\r\n this.dispatchEvent(new CustomEvent('deleteinterceptor', { detail: index, bubbles: true, composed: true }));\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${TEST_PREVISUALIZER_STYLES}</style>${renderTestPrevisualizer(\r\n this._commands,\r\n this._interceptors,\r\n this._showInterceptors,\r\n this.editable,\r\n this.t.bind(this),\r\n )}`;\r\n\r\n const cmdsEl = this.shadow.querySelector<HTMLElement>('[data-ref=\"cmds\"]');\r\n if (cmdsEl) cmdsEl.scrollTop = cmdsEl.scrollHeight;\r\n\r\n this.shadow.querySelector('[data-action=\"copy\"]')?.addEventListener('click', () => this.copyToClipboard());\r\n this.shadow.querySelector('[data-action=\"toggle-icp\"]')?.addEventListener('click', () => this.toggleInterceptors());\r\n this.shadow.querySelector('[data-action=\"copy-icp\"]')?.addEventListener('click', () => this.copyInterceptorsToClipboard());\r\n\r\n if (this.editable) {\r\n this.shadow.querySelectorAll('[data-del]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.dispatchDelete(Number((btn as HTMLElement).dataset['del']));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-move-up]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n const idx = Number((btn as HTMLElement).dataset['moveUp']);\r\n this.dispatchMove(idx, idx - 1);\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-move-dn]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n const idx = Number((btn as HTMLElement).dataset['moveDn']);\r\n this.dispatchMove(idx, idx + 1);\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-del-icp]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.dispatchDeleteInterceptor(Number((btn as HTMLElement).dataset['delIcp']));\r\n });\r\n });\r\n }\r\n }\r\n}\r\n\r\nif (!customElements.get('test-previsualizer')) {\r\n customElements.define('test-previsualizer', TestPrevisualizerElement);\r\n}\r\n","export const SAVE_TEST_STYLES = `\n :host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n .container { padding: 24px 28px; text-align: left; }\n .btn-row, p { text-align: center; }\n p { margin: 0 0 20px; font-size: 14px; color: #8b949e; line-height: 1.5; }\n .btn-row { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }\n button {\n padding: 7px 16px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; transition: filter 0.15s, transform 0.1s;\n letter-spacing: 0.1px;\n }\n button:hover { filter: brightness(1.1); }\n button:active { transform: scale(0.97); }\n .btn-primary { background: #2f81f7; color: #fff; }\n .btn-success { background: #3fb950; color: #fff; }\n .btn-danger { background: transparent; color: #f85149; border: 1px solid rgba(248,81,73,0.5); }\n .btn-danger:hover { background: rgba(248,81,73,0.08); filter: none; }\n input[type=\"text\"] {\n width: 100%; padding: 10px 14px; border: 1px solid #30363d;\n border-radius: 8px; background: #0d1117; color: #e6edf3;\n font-size: 14px; outline: none; margin-bottom: 4px;\n transition: border-color 0.15s, box-shadow 0.15s;\n }\n input[type=\"text\"]:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }\n input[type=\"text\"]::placeholder { color: #484f58; }\n textarea {\n width: 100%; padding: 10px 14px; border: 1px solid #30363d;\n border-radius: 8px; background: #0d1117; color: #e6edf3;\n font-size: 14px; outline: none; margin-bottom: 4px;\n font-family: inherit; resize: vertical; line-height: 1.5;\n transition: border-color 0.15s, box-shadow 0.15s;\n }\n textarea:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }\n textarea::placeholder { color: #484f58; }\n .tag-label {\n font-size: 11px; color: #484f58; text-align: left; margin-bottom: 5px; display: block;\n }\n .tag-input-row { display: flex; gap: 6px; margin-bottom: 8px; }\n .tag-input-row input[type=\"text\"] {\n font-size: 12px; padding: 6px 10px; margin: 0;\n }\n .btn-tag-add {\n padding: 6px 12px; font-size: 12px; background: #21262d; color: #8b949e;\n border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n transition: background 0.15s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-tag-add:hover { background: #30363d; color: #e6edf3; filter: none; }\n .chips { display: flex; flex-wrap: wrap; gap: 5px; min-height: 24px; text-align: left; }\n .chip {\n display: inline-flex; align-items: center; gap: 5px;\n background: rgba(47,129,247,0.15); color: #2f81f7;\n border: 1px solid rgba(47,129,247,0.3); border-radius: 20px;\n padding: 2px 10px 2px 10px; font-size: 11px; font-weight: 500;\n }\n .chip-del {\n cursor: pointer; color: #8b949e; font-size: 12px; line-height: 1;\n transition: color 0.12s; padding: 0; background: none; border: none;\n }\n .chip-del:hover { color: #f85149; filter: none; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\n\nexport function renderSaveTestAsk(t: (key: string) => string): string {\n return `\n <div class=\"container\">\n <p>${t('SAVE_TEST.ASK')}</p>\n <div class=\"btn-row\">\n <button class=\"btn-primary\" id=\"btn-yes\">${t('SAVE_TEST.YES_CONTINUE')}</button>\n <button class=\"btn-danger\" id=\"btn-no\">${t('SAVE_TEST.NO_DISCARD')}</button>\n </div>\n </div>`;\n}\n\nexport function renderSaveTestDesc(description: string, notes: string, tags: string[], t: (key: string) => string): string {\n const chipsHtml = tags.map((tag) =>\n `<span class=\"chip\">${escHtml(tag)}<button class=\"chip-del\" data-tag=\"${escAttr(tag)}\" title=\"${t('SAVE_TEST.REMOVE_TAG_TITLE')}\">β</button></span>`\n ).join('');\n\n return `\n <div class=\"container\">\n <p>${t('SAVE_TEST.DESC_LABEL')} (<code>it()</code>):</p>\n <input id=\"desc-input\" type=\"text\" placeholder=\"${t('SAVE_TEST.DESC_PLACEHOLDER')}\"\n value=\"${escAttr(description)}\" autocomplete=\"off\" />\n <span class=\"tag-label\">${t('SAVE_TEST.NOTES_LABEL')}</span>\n <textarea id=\"notes-input\" rows=\"3\" placeholder=\"${escAttr(t('SAVE_TEST.NOTES_PLACEHOLDER'))}\">${escHtml(notes)}</textarea>\n <span class=\"tag-label\">${t('SAVE_TEST.TAGS_LABEL')}</span>\n <div class=\"tag-input-row\">\n <input id=\"tag-input\" type=\"text\" placeholder=\"${t('SAVE_TEST.TAGS_PLACEHOLDER')}\" autocomplete=\"off\" />\n <button class=\"btn-tag-add\" id=\"btn-add-tag\">${t('SAVE_TEST.ADD_TAG')}</button>\n </div>\n <div class=\"chips\" id=\"chips-container\">${chipsHtml || `<span style=\"color:#484f58;font-size:11px\">${t('SAVE_TEST.NO_TAGS')}</span>`}</div>\n <div class=\"btn-row\">\n <button class=\"btn-primary\" id=\"btn-confirm\">${t('SAVE_TEST.SAVE_BTN')}</button>\n <button class=\"btn-success\" id=\"btn-export\">${t('SAVE_TEST.SAVE_AND_EDIT')}</button>\n <button class=\"btn-danger\" id=\"btn-cancel\">${t('SAVE_TEST.CANCEL')}</button>\n </div>\n </div>`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\nimport { SAVE_TEST_STYLES } from './save-test.styles';\nimport { renderSaveTestAsk, renderSaveTestDesc } from './save-test.template';\n\nexport class SaveTestElement extends HTMLElement {\n private shadow: ShadowRoot;\n private _step: 'ask' | 'desc' = 'ask';\n description = '';\n notes = '';\n tags: string[] = [];\n translation: TranslationService = translationService;\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void { this.render(); }\n\n get step(): 'ask' | 'desc' { return this._step; }\n\n askSave(): void { this._step = 'desc'; this.render(); }\n\n confirmSave(): void { this.dispatch('savetest', { description: this.description.trim(), notes: this.notes, tags: [...this.tags] }); }\n\n confirmSaveAndExport(): void { this.dispatch('saveandexport', { description: this.description.trim(), notes: this.notes, tags: [...this.tags] }); }\n\n cancel(): void { this.dispatch('savetest', { description: null, notes: '', tags: [] }); }\n\n restartComponent(): void { this._step = 'ask'; this.description = ''; this.notes = ''; this.tags = []; this.render(); }\n\n addTag(tag: string): void {\n const t = tag.trim().replace(/[,;]/g, '');\n if (t && !this.tags.includes(t)) {\n this.tags = [...this.tags, t];\n this.render();\n }\n }\n\n removeTag(tag: string): void {\n this.tags = this.tags.filter((t) => t !== tag);\n this.render();\n }\n\n private t(key: string): string { return this.translation.translate(key); }\n\n private dispatch(type: string, detail: { description: string | null; notes: string; tags: string[] }): void {\n this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));\n }\n\n private render(): void {\n if (this._step === 'ask') {\n this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestAsk(this.t.bind(this))}`;\n this.shadow.getElementById('btn-yes')?.addEventListener('click', () => this.askSave());\n this.shadow.getElementById('btn-no')?.addEventListener('click', () => this.cancel());\n } else {\n this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.notes, this.tags, this.t.bind(this))}`;\n\n const descInput = this.shadow.getElementById('desc-input') as HTMLInputElement;\n const notesInput = this.shadow.getElementById('notes-input') as HTMLTextAreaElement;\n const tagInput = this.shadow.getElementById('tag-input') as HTMLInputElement;\n\n descInput.addEventListener('input', () => { this.description = descInput.value; });\n notesInput.addEventListener('input', () => { this.notes = notesInput.value; });\n\n const tryAddTag = () => {\n this.addTag(tagInput.value);\n tagInput.value = '';\n };\n this.shadow.getElementById('btn-add-tag')?.addEventListener('click', tryAddTag);\n tagInput.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); tryAddTag(); }\n });\n\n this.shadow.querySelectorAll<HTMLButtonElement>('.chip-del').forEach((btn) => {\n btn.addEventListener('click', () => this.removeTag(btn.dataset['tag'] ?? ''));\n });\n\n this.shadow.getElementById('btn-confirm')?.addEventListener('click', () => this.confirmSave());\n this.shadow.getElementById('btn-export')?.addEventListener('click', () => this.confirmSaveAndExport());\n this.shadow.getElementById('btn-cancel')?.addEventListener('click', () => this.cancel());\n setTimeout(() => descInput.focus(), 60);\n }\n }\n}\n\nif (!customElements.get('save-test')) {\n customElements.define('save-test', SaveTestElement);\n}\n","export const TEST_EDITOR_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .toolbar {\n display: flex; align-items: center; gap: 6px; padding: 8px 10px; flex-shrink: 0;\n background: #161b22; border-bottom: 1px solid #21262d; flex-wrap: wrap;\n }\n .tag-filter { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; }\n .tag-chip {\n padding: 2px 10px; border-radius: 20px; cursor: pointer; font-size: 11px; font-weight: 500;\n border: 1px solid #30363d; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s, border-color 0.12s;\n }\n .tag-chip:hover { background: #30363d; color: #e6edf3; }\n .tag-chip.active { background: rgba(47,129,247,0.2); color: #2f81f7; border-color: rgba(47,129,247,0.4); }\n .btn-select {\n padding: 4px 12px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-select:hover { background: #30363d; color: #e6edf3; }\n .btn-select.active { background: rgba(47,129,247,0.15); color: #2f81f7; border-color: rgba(47,129,247,0.3); }\n .describe-bar {\n display: flex; align-items: center; gap: 8px; padding: 8px 10px;\n background: rgba(47,129,247,0.06); border-bottom: 1px solid rgba(47,129,247,0.2);\n flex-wrap: wrap;\n }\n .describe-bar input {\n flex: 1; min-width: 150px; padding: 5px 10px; background: #0d1117;\n border: 1px solid #30363d; border-radius: 6px; color: #e6edf3;\n font-size: 12px; outline: none;\n }\n .describe-bar input:focus { border-color: #2f81f7; }\n .btn-gen-describe {\n padding: 5px 14px; border: 1px solid #2f81f7; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: rgba(47,129,247,0.15); color: #2f81f7;\n transition: background 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-gen-describe:hover { background: rgba(47,129,247,0.25); }\n .selected-count { font-size: 11px; color: #8b949e; }\n .describe-bar { flex-shrink: 0; }\n .list { padding: 8px; flex: 1; min-height: 0; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent; }\n .list::-webkit-scrollbar { width: 4px; }\n .list::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .empty { color: #484f58; text-align: center; padding: 32px; font-size: 13px; }\n .row {\n background: #0d1117; border-radius: 8px; margin-bottom: 6px;\n overflow: hidden; border: 1px solid #21262d;\n transition: border-color 0.15s;\n }\n .row:hover { border-color: #30363d; }\n .row.selected-row { border-color: rgba(47,129,247,0.5); }\n .row-header {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px; cursor: pointer; user-select: none;\n }\n .row-header:hover { background: rgba(48,54,61,0.3); }\n .test-name { flex: 1; font-size: 13px; font-weight: 500; color: #e6edf3; }\n .test-date { font-size: 10.5px; color: #484f58; margin-right: 4px; }\n .test-tags { display: flex; gap: 4px; margin-right: 4px; }\n .test-tag {\n padding: 1px 7px; border-radius: 20px; font-size: 10px;\n background: rgba(47,129,247,0.1); color: #8b949e; border: 1px solid rgba(47,129,247,0.2);\n }\n .btn-icon {\n padding: 3px 8px; border: none; border-radius: 6px; cursor: pointer;\n font-size: 11px; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n .btn-icon:hover { background: #30363d; color: #e6edf3; }\n .btn-del:hover { background: rgba(248,81,73,0.15); color: #f85149; }\n input[type=\"checkbox\"] {\n width: 14px; height: 14px; accent-color: #2f81f7; cursor: pointer; flex-shrink: 0;\n }\n .row-body {\n background: #0d1117; padding: 10px 14px;\n border-top: 1px solid #21262d;\n }\n .test-notes {\n margin: 0 0 10px; padding: 8px 12px;\n background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);\n border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;\n line-height: 1.6; white-space: pre-wrap; word-break: break-word;\n }\n .code-preview {\n margin: 0; padding: 10px 12px; background: #161b22;\n border-radius: 6px; border: 1px solid #21262d;\n font-size: 11px; color: #c9d1d9; line-height: 1.7;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n overflow-x: auto; white-space: pre;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .code-preview::-webkit-scrollbar { height: 4px; }\n .code-preview::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .code-preview-icp { margin-top: 8px; }\n .sh-kw { color: #ff7b72; }\n .sh-bi { color: #d2a8ff; }\n .sh-str { color: #a5d6ff; }\n .sh-cmt { color: #8b949e; font-style: italic; }\n .sh-num { color: #79c0ff; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\nimport { syntaxHighlight } from '../../utils/syntax-highlight.utils';\nimport { normalizeBlock, escapeSingleQuotes } from '../../utils/code-format.utils';\nimport type { TestWithDetails } from '../../services/persistence.service';\n\nexport interface TestEditorState {\n tags: string[];\n visible: TestWithDetails[];\n selectedVisible: TestWithDetails[];\n activeTag: string | null;\n selectMode: boolean;\n selectedIds: Set<number>;\n describeName: string;\n expandedIndex: number | null;\n interceptorsByTest: Record<number, string[]>;\n locale: string;\n}\n\nexport function renderTestEditor(state: TestEditorState, t: (key: string) => string): string {\n const { tags, visible, selectedVisible, activeTag, selectMode, selectedIds, describeName, expandedIndex, interceptorsByTest, locale } = state;\n\n const tagFilterHtml = tags.length\n ? `<div class=\"tag-filter\">\n ${tags.map((tag) => `<button class=\"tag-chip${activeTag === tag ? ' active' : ''}\" data-filter-tag=\"${escAttr(tag)}\">${escHtml(tag)}</button>`).join('')}\n </div>`\n : `<div class=\"tag-filter\" style=\"color:#484f58;font-size:11px\">${t('TEST_EDITOR.NO_TAGS')}</div>`;\n\n const describeBarHtml = selectMode && selectedVisible.length > 0\n ? `<div class=\"describe-bar\">\n <span class=\"selected-count\">${selectedVisible.length} ${selectedVisible.length !== 1 ? t('TEST_EDITOR.SELECTED_PLURAL') : t('TEST_EDITOR.SELECTED_SINGULAR')}</span>\n <input id=\"describe-name\" type=\"text\" placeholder=\"${t('TEST_EDITOR.DESCRIBE_PLACEHOLDER')}\" value=\"${escAttr(describeName)}\" />\n <button class=\"btn-gen-describe\" id=\"btn-gen-describe\">${t('TEST_EDITOR.COPY_DESCRIBE')}</button>\n </div>`\n : '';\n\n const rows = visible.map((test, i) => {\n const expanded = expandedIndex === i;\n const date = new Date(test.createdAt).toLocaleString(locale, { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });\n const icps = interceptorsByTest[test.id] ?? test.interceptors ?? [];\n const tagsHtml = (test.tags ?? []).length\n ? `<span class=\"test-tags\">${(test.tags ?? []).map((tag) => `<span class=\"test-tag\">${escHtml(tag)}</span>`).join('')}</span>`\n : '';\n const checkbox = selectMode\n ? `<input type=\"checkbox\" ${selectedIds.has(test.id) ? 'checked' : ''} data-select=\"${test.id}\" />`\n : '';\n const hasIcps = (test.interceptors ?? []).length > 0;\n const itBlockCode = `it('${escapeSingleQuotes(test.name)}', () => {\\n${(test.commands ?? []).map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});`;\n const icpBlockCode = icps.length ? `beforeEach(() => {\\n // Auto-generated Cypress interceptors\\n${icps.map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});` : '';\n const notesHtml = (expanded && test.notes)\n ? `<p class=\"test-notes\">${escHtml(test.notes)}</p>`\n : '';\n const body = expanded ? `\n <div class=\"row-body\">\n ${notesHtml}\n <pre class=\"code-preview\">${syntaxHighlight(itBlockCode)}</pre>\n ${icpBlockCode ? `<pre class=\"code-preview code-preview-icp\">${syntaxHighlight(icpBlockCode)}</pre>` : ''}\n </div>` : '';\n return `\n <div class=\"row${selectedIds.has(test.id) ? ' selected-row' : ''}\">\n <div class=\"row-header\" data-action=\"expand\" data-idx=\"${i}\">\n ${checkbox}\n <span class=\"test-name\">${escHtml(test.name)}</span>\n ${tagsHtml}\n <span class=\"test-date\">${date}</span>\n <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>\n ${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>` : ''}\n <button class=\"btn-icon btn-del\" data-action=\"delete\" data-id=\"${test.id}\" title=\"${t('TEST_EDITOR.DELETE_TITLE')}\">π</button>\n </div>\n ${body}\n </div>`;\n }).join('');\n\n return `\n <div class=\"toolbar\">\n ${tagFilterHtml}\n <button class=\"btn-select${selectMode ? ' active' : ''}\" id=\"btn-select-mode\">\n ${selectMode ? t('TEST_EDITOR.CANCEL_SELECT') : t('TEST_EDITOR.MULTI_SELECT')}\n </button>\n </div>\n ${describeBarHtml}\n <div class=\"list\">\n ${visible.length ? rows : `<div class=\"empty\">${t('TEST_EDITOR.NO_TESTS')}</div>`}\n </div>`;\n}\n","import { escHtml } from './html.utils';\n\nconst KEYWORDS = new Set([\n 'describe', 'it', 'xit', 'fit', 'xdescribe', 'fdescribe',\n 'beforeEach', 'afterEach', 'before', 'after', 'context',\n 'const', 'let', 'var', 'function', 'return', 'if', 'else',\n 'import', 'export', 'from', 'new', 'this', 'null', 'undefined',\n 'true', 'false', 'async', 'await', 'of', 'in', 'typeof', 'void',\n]);\n\nconst BUILTINS = new Set(['cy', 'expect', 'assert', 'Cypress', 'chai']);\n\nexport function syntaxHighlight(code: string): string {\n return code.split('\\n').map(highlightLine).join('\\n');\n}\n\nfunction highlightLine(line: string): string {\n let result = '';\n let i = 0;\n const len = line.length;\n\n while (i < len) {\n // Single-line comment\n if (line[i] === '/' && i + 1 < len && line[i + 1] === '/') {\n result += `<span class=\"sh-cmt\">${escHtml(line.slice(i))}</span>`;\n return result;\n }\n // String literal (single, double, or template)\n const q = line[i];\n if (q === \"'\" || q === '\"' || q === '`') {\n let j = i + 1;\n while (j < len) {\n if (line[j] === '\\\\') { j += 2; continue; }\n if (line[j] === q) { j++; break; }\n j++;\n }\n result += `<span class=\"sh-str\">${escHtml(line.slice(i, j))}</span>`;\n i = j;\n continue;\n }\n // Number (not preceded by identifier character)\n if (/[0-9]/.test(line[i]) && (i === 0 || !/[a-zA-Z_$]/.test(line[i - 1]))) {\n let j = i;\n while (j < len && /[0-9.]/.test(line[j])) j++;\n result += `<span class=\"sh-num\">${escHtml(line.slice(i, j))}</span>`;\n i = j;\n continue;\n }\n // Identifier, keyword, or builtin\n if (/[a-zA-Z_$]/.test(line[i])) {\n let j = i;\n while (j < len && /[a-zA-Z0-9_$]/.test(line[j])) j++;\n const word = line.slice(i, j);\n if (KEYWORDS.has(word)) {\n result += `<span class=\"sh-kw\">${escHtml(word)}</span>`;\n } else if (BUILTINS.has(word)) {\n result += `<span class=\"sh-bi\">${escHtml(word)}</span>`;\n } else {\n result += escHtml(word);\n }\n i = j;\n continue;\n }\n result += escHtml(line[i]);\n i++;\n }\n return result;\n}\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\nimport { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { localeForLang } from '../../models/lang.model';\r\nimport { escapeSingleQuotes } from '../../utils/code-format.utils';\r\nimport { TEST_EDITOR_STYLES } from './test-editor.styles';\r\nimport { renderTestEditor } from './test-editor.template';\r\n\r\nexport class TestEditorElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n persistence!: PersistenceService;\r\n translation: TranslationService = translationService;\r\n tests: TestWithDetails[] = [];\r\n expandedIndex: number | null = null;\r\n interceptorsByTest: Record<number, string[]> = {};\r\n activeTag: string | null = null;\r\n selectMode = false;\r\n selectedIds: Set<number> = new Set();\r\n describeName = '';\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n this.loadTests();\r\n }\r\n\r\n async loadTests(): Promise<void> {\r\n this.tests = await this.persistence.getAllTests();\r\n this.render();\r\n }\r\n\r\n async deleteTest(id: number): Promise<void> {\r\n await this.persistence.deleteTest(id);\r\n this.selectedIds.delete(id);\r\n await this.loadTests();\r\n }\r\n\r\n toggleExpand(index: number): void {\r\n this.expandedIndex = this.expandedIndex === index ? null : index;\r\n if (this.expandedIndex !== null) {\r\n const test = this.tests[this.expandedIndex];\r\n if (test?.id && !this.interceptorsByTest[test.id]) {\r\n this.interceptorsByTest[test.id] = Array.isArray(test.interceptors) ? test.interceptors : [];\r\n }\r\n }\r\n this.render();\r\n }\r\n\r\n hasInterceptors(testId: number): boolean {\r\n return Array.isArray(this.interceptorsByTest[testId]) && this.interceptorsByTest[testId].length > 0;\r\n }\r\n\r\n toggleSelectMode(): void {\r\n this.selectMode = !this.selectMode;\r\n if (!this.selectMode) this.selectedIds.clear();\r\n this.render();\r\n }\r\n\r\n toggleSelectTest(id: number): void {\r\n if (this.selectedIds.has(id)) this.selectedIds.delete(id);\r\n else this.selectedIds.add(id);\r\n this.render();\r\n }\r\n\r\n generateDescribe(): void {\r\n const selected = this.tests.filter((t) => this.selectedIds.has(t.id));\r\n if (!selected.length) return;\r\n\r\n const name = this.describeName.trim() || this.t('TEST_EDITOR.DEFAULT_DESCRIBE');\r\n\r\n const allInterceptors = [...new Set(\r\n selected.flatMap((t) => this.interceptorsByTest[t.id] ?? t.interceptors ?? [])\r\n )];\r\n\r\n const beforeEach = allInterceptors.length\r\n ? ` beforeEach(() => {\\n // Auto-generated Cypress interceptors\\n ${allInterceptors.join('\\n ')}\\n });\\n\\n`\r\n : '';\r\n\r\n const itBlocks = selected\r\n .map((t) => {\r\n const cmds = (t.commands ?? []).map((c) => ` ${c}`).join('\\n');\r\n return ` it('${escapeSingleQuotes(t.name ?? '')}', () => {\\n${cmds}\\n });`;\r\n })\r\n .join('\\n\\n');\r\n\r\n const block = `describe('${escapeSingleQuotes(name)}', () => {\\n${beforeEach}${itBlocks}\\n});`;\r\n navigator.clipboard?.writeText(block);\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n get allTags(): string[] {\r\n const tagSet = new Set<string>();\r\n this.tests.forEach((t) => (t.tags ?? []).forEach((tag) => tagSet.add(tag)));\r\n return [...tagSet].sort();\r\n }\r\n\r\n get visibleTests(): TestWithDetails[] {\r\n const tag = this.activeTag;\r\n if (!tag) return this.tests;\r\n return this.tests.filter((t) => (t.tags ?? []).includes(tag));\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private render(): void {\r\n const tags = this.allTags;\r\n const visible = this.visibleTests;\r\n const selectedVisible = visible.filter((t) => this.selectedIds.has(t.id));\r\n\r\n this.shadow.innerHTML = `<style>${TEST_EDITOR_STYLES}</style>${renderTestEditor({\r\n tags,\r\n visible,\r\n selectedVisible,\r\n activeTag: this.activeTag,\r\n selectMode: this.selectMode,\r\n selectedIds: this.selectedIds,\r\n describeName: this.describeName,\r\n expandedIndex: this.expandedIndex,\r\n interceptorsByTest: this.interceptorsByTest,\r\n locale: localeForLang(this.translation.getLang()),\r\n }, this.t.bind(this))}`;\r\n\r\n this.shadow.getElementById('btn-select-mode')?.addEventListener('click', () => this.toggleSelectMode());\r\n\r\n this.shadow.querySelectorAll('[data-filter-tag]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const tag = (el as HTMLElement).dataset['filterTag'] ?? '';\r\n if (!tag) return;\r\n this.activeTag = this.activeTag === tag ? null : tag;\r\n this.render();\r\n });\r\n });\r\n\r\n const descInput = this.shadow.getElementById('describe-name') as HTMLInputElement | null;\r\n if (descInput) {\r\n descInput.addEventListener('input', () => { this.describeName = descInput.value; });\r\n }\r\n this.shadow.getElementById('btn-gen-describe')?.addEventListener('click', () => {\r\n this.describeName = descInput?.value ?? this.describeName;\r\n this.generateDescribe();\r\n });\r\n\r\n this.shadow.querySelectorAll('[data-select]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n this.toggleSelectTest(Number((el as HTMLElement).dataset['select']));\r\n });\r\n });\r\n\r\n this.shadow.querySelectorAll('[data-action=\"expand\"]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n if (this.selectMode) {\r\n const row = visible[Number((el as HTMLElement).dataset['idx'])];\r\n if (row) this.toggleSelectTest(row.id);\r\n } else {\r\n this.toggleExpand(Number((el as HTMLElement).dataset['idx']));\r\n }\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"delete\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n this.deleteTest(Number((el as HTMLElement).dataset['id']));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"copy-cmds\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n const idx = Number((el as HTMLElement).dataset['idx']);\r\n this.copyToClipboard((visible[idx]?.commands ?? []).join('\\n'));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"copy-icps\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n const idx = Number((el as HTMLElement).dataset['idx']);\r\n const t = visible[idx];\r\n this.copyToClipboard((this.interceptorsByTest[t?.id] ?? t?.interceptors ?? []).join('\\n'));\r\n });\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('test-editor')) {\r\n customElements.define('test-editor', TestEditorElement);\r\n}\r\n","export const CONFIGURATION_STYLES = `\n :host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n\n /* ββ Grid container βββββββββββββββββββββββββββββββββββββ */\n .cfg-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n padding: 14px;\n }\n\n /* ββ Cards ββββββββββββββββββββββββββββββββββββββββββββββ */\n .card {\n background: #161b22;\n border: 1px solid #21262d;\n border-radius: 10px;\n padding: 14px 16px;\n transition: border-color 0.15s;\n }\n .card:hover { border-color: #30363d; }\n .card-wide { grid-column: 1 / -1; }\n\n /* ββ Card header ββββββββββββββββββββββββββββββββββββββββ */\n .card-hd {\n display: flex; align-items: center; gap: 7px;\n font-size: 10px; font-weight: 700; text-transform: uppercase;\n letter-spacing: 0.8px; color: #484f58; margin-bottom: 12px;\n }\n .card-hd-icon { font-size: 13px; }\n\n /* ββ Language βββββββββββββββββββββββββββββββββββββββββββ */\n .field-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .field-label { font-size: 12px; color: #8b949e; }\n select {\n background: #0d1117; color: #e6edf3; border: 1px solid #30363d;\n border-radius: 6px; padding: 6px 10px; font-size: 12px; outline: none;\n cursor: pointer; transition: border-color 0.15s; flex-shrink: 0;\n }\n select:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.12); }\n\n /* ββ HTTP toggle ββββββββββββββββββββββββββββββββββββββββ */\n .check-row {\n display: flex; align-items: flex-start; gap: 10px;\n cursor: pointer; user-select: none;\n }\n input[type=\"checkbox\"] { width: 15px; height: 15px; margin-top: 2px; cursor: pointer; accent-color: #2f81f7; flex-shrink: 0; }\n .check-title { font-size: 12px; color: #c9d1d9; margin-bottom: 3px; }\n .check-sub { font-size: 10px; color: #484f58; line-height: 1.5; }\n\n /* ββ Cypress folder βββββββββββββββββββββββββββββββββββββ */\n .fs-layout { display: flex; gap: 12px; align-items: flex-start; }\n .fs-tree {\n flex-shrink: 0;\n margin: 0; padding: 8px 10px;\n background: #0d1117; border: 1px solid #21262d; border-radius: 6px;\n font-size: 10px; color: #c9d1d9; line-height: 1.8;\n font-family: 'Cascadia Code','Fira Code','Consolas',monospace;\n }\n .fs-right { display: flex; flex-direction: column; gap: 10px; flex: 1; }\n .fs-status {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: #8b949e;\n background: #0d1117; border: 1px solid #21262d; border-radius: 6px;\n padding: 8px 10px;\n }\n .fs-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }\n .fs-dot.on { background: #3fb950; box-shadow: 0 0 6px rgba(63,185,80,.5); }\n .fs-dot.off { background: #484f58; }\n .fs-folder { color: #e6edf3; font-family: 'Cascadia Code','Fira Code','Consolas',monospace; font-size: 11px; }\n\n /* ββ Buttons ββββββββββββββββββββββββββββββββββββββββββββ */\n .btn-row { display: flex; gap: 8px; flex-wrap: wrap; }\n button {\n padding: 7px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s, border-color 0.15s;\n }\n button:hover { background: #30363d; color: #e6edf3; border-color: #484f58; }\n .btn-import {\n display: inline-block;\n padding: 7px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s, border-color 0.15s;\n }\n .btn-import:hover { background: #30363d; color: #e6edf3; border-color: #484f58; }\n .btn-danger { border-color: rgba(248,81,73,.4); color: #f85149; background: transparent; }\n .btn-danger:hover { background: rgba(248,81,73,.08); border-color: #f85149; color: #f85149; }\n .file-input { display: none; }\n\n /* ββ Data section desc ββββββββββββββββββββββββββββββββββ */\n .data-desc { font-size: 11px; color: #484f58; margin-bottom: 10px; line-height: 1.5; }\n\n /* ββ Export overlay (modal) βββββββββββββββββββββββββββββ */\n .export-overlay {\n position: fixed; inset: 0; z-index: 100000;\n background: rgba(1,4,9,0.7);\n display: flex; align-items: center; justify-content: center; padding: 20px;\n }\n .export-modal {\n width: 640px; max-width: 100%; max-height: 86vh;\n display: flex; flex-direction: column;\n background: #161b22; border: 1px solid #30363d; border-radius: 12px;\n box-shadow: 0 12px 40px rgba(0,0,0,0.5); overflow: hidden;\n }\n .export-hd {\n padding: 14px 18px; font-size: 13px; font-weight: 700;\n border-bottom: 1px solid #21262d; color: #e6edf3;\n }\n .export-modes { display: flex; gap: 6px; padding: 12px 18px 0; }\n .export-mode {\n flex: 1; padding: 7px 10px; font-size: 11px; border-radius: 6px;\n background: #0d1117; border: 1px solid #30363d; color: #8b949e;\n }\n .export-mode:hover { background: #21262d; color: #e6edf3; }\n .export-mode.active { background: rgba(47,129,247,0.15); border-color: #2f81f7; color: #2f81f7; }\n .export-body {\n padding: 14px 18px; overflow-y: auto; flex: 1; min-height: 160px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .export-tag-hint { font-size: 12px; color: #484f58; margin-top: 12px; }\n .export-result-label {\n font-size: 10px; color: #484f58; text-transform: uppercase; letter-spacing: 0.6px;\n font-weight: 600; margin: 14px 0 6px;\n }\n .export-row-static { cursor: default; }\n .export-row-static:hover { background: transparent; }\n .export-all-desc { font-size: 12px; color: #8b949e; }\n .export-empty { font-size: 12px; color: #484f58; text-align: center; padding: 20px; }\n .export-list { display: flex; flex-direction: column; gap: 4px; }\n .export-row {\n display: flex; align-items: center; gap: 8px;\n padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 12px; color: #c9d1d9;\n }\n .export-row:hover { background: #0d1117; }\n .export-row-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .export-row-tag {\n font-size: 9px; color: #8b949e; background: #0d1117;\n border: 1px solid #30363d; border-radius: 10px; padding: 1px 7px; flex-shrink: 0;\n }\n .export-tags { display: flex; flex-wrap: wrap; gap: 6px; }\n .export-tag {\n padding: 4px 10px; font-size: 11px; border-radius: 12px;\n background: #0d1117; border: 1px solid #30363d; color: #8b949e;\n }\n .export-tag:hover { background: #21262d; color: #e6edf3; }\n .export-tag.active { background: rgba(47,129,247,0.15); border-color: #2f81f7; color: #2f81f7; }\n .export-ft {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n padding: 12px 18px; border-top: 1px solid #21262d;\n }\n .export-count { font-size: 11px; color: #8b949e; }\n .export-count b { color: #e6edf3; }\n .export-ft-actions { display: flex; gap: 8px; }\n .btn-export-confirm { background: #238636; border-color: #238636; color: #fff; }\n .btn-export-confirm:hover:not(:disabled) { background: #2ea043; border-color: #2ea043; }\n .btn-export-confirm:disabled { opacity: 0.45; cursor: not-allowed; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\r\nimport { selectTestsForExport, type ExportMode } from '../../utils/export-selection.utils';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\n\r\nexport const LANGS = [\r\n { value: 'es', label: 'EspaΓ±ol' },\r\n { value: 'en', label: 'English' },\r\n { value: 'fr', label: 'FranΓ§ais' },\r\n { value: 'it', label: 'Italiano' },\r\n { value: 'de', label: 'Deutsch' },\r\n];\r\n\r\nexport interface ConfigurationState {\r\n selectedLanguage: string;\r\n advancedHttpConfig: boolean;\r\n selectorStrategy: string;\r\n filesystemGranted: boolean;\r\n cypressFolderName: string | null;\r\n smartSelectorEnabled: boolean;\r\n startHidden: boolean;\r\n resumeTtlMinutes: number;\r\n isExporting: boolean;\r\n exportMode: ExportMode;\r\n exportTests: TestWithDetails[];\r\n exportSelectedIds: Set<number>;\r\n exportSelectedTags: Set<string>;\r\n}\r\n\r\nexport function renderExportOverlay(state: ConfigurationState, t: (key: string) => string): string {\r\n const { isExporting, exportMode, exportTests, exportSelectedIds, exportSelectedTags } = state;\r\n if (!isExporting) return '';\r\n\r\n const count = selectTestsForExport(exportTests, exportMode, {\r\n ids: exportSelectedIds,\r\n tags: exportSelectedTags,\r\n }).length;\r\n\r\n const modeBtn = (mode: ExportMode, key: string) =>\r\n `<button class=\"export-mode ${exportMode === mode ? 'active' : ''}\" data-export-mode=\"${mode}\">${t(key)}</button>`;\r\n\r\n let body: string;\r\n if (exportTests.length === 0) {\r\n body = `<div class=\"export-empty\">${t('CONFIG.EXPORT_EMPTY')}</div>`;\r\n } else if (exportMode === 'all') {\r\n body = `<div class=\"export-all-desc\">${t('CONFIG.EXPORT_ALL_DESC')}</div>`;\r\n } else if (exportMode === 'manual') {\r\n body = `<div class=\"export-list\">${exportTests.map((test) => `\r\n <label class=\"export-row\">\r\n <input type=\"checkbox\" data-export-test=\"${test.id}\" ${exportSelectedIds.has(test.id) ? 'checked' : ''} />\r\n <span class=\"export-row-name\">${escHtml(test.name)}</span>\r\n ${(test.tags ?? []).map((tag) => `<span class=\"export-row-tag\">${escHtml(tag)}</span>`).join('')}\r\n </label>`).join('')}</div>`;\r\n } else {\r\n const allTags = [...new Set(exportTests.flatMap((test) => test.tags ?? []))].sort();\r\n if (!allTags.length) {\r\n body = `<div class=\"export-empty\">${t('CONFIG.EXPORT_NO_TAGS')}</div>`;\r\n } else {\r\n const chips = `<div class=\"export-tags\">${allTags.map((tag) =>\r\n `<button class=\"export-tag ${exportSelectedTags.has(tag) ? 'active' : ''}\" data-export-tag=\"${escAttr(tag)}\">${escHtml(tag)}</button>`).join('')}</div>`;\r\n // Preview the tests that the selected tags resolve to, so QA sees exactly\r\n // what will be exported.\r\n const matched = selectTestsForExport(exportTests, 'tags', { tags: exportSelectedTags });\r\n const preview = exportSelectedTags.size === 0\r\n ? `<div class=\"export-tag-hint\">${t('CONFIG.EXPORT_TAGS_HINT')}</div>`\r\n : `<div class=\"export-result-label\">${t('CONFIG.EXPORT_RESULT_LABEL')}</div>\r\n <div class=\"export-list\">${matched.map((test) => `\r\n <div class=\"export-row export-row-static\">\r\n <span class=\"export-row-name\">${escHtml(test.name)}</span>\r\n ${(test.tags ?? []).map((tag) => `<span class=\"export-row-tag\">${escHtml(tag)}</span>`).join('')}\r\n </div>`).join('')}</div>`;\r\n body = chips + preview;\r\n }\r\n }\r\n\r\n return `\r\n <div class=\"export-overlay\" id=\"export-overlay\">\r\n <div class=\"export-modal\">\r\n <div class=\"export-hd\">${t('CONFIG.EXPORT_DIALOG_TITLE')}</div>\r\n ${exportTests.length ? `<div class=\"export-modes\">\r\n ${modeBtn('all', 'CONFIG.EXPORT_MODE_ALL')}\r\n ${modeBtn('manual', 'CONFIG.EXPORT_MODE_MANUAL')}\r\n ${modeBtn('tags', 'CONFIG.EXPORT_MODE_TAGS')}\r\n </div>` : ''}\r\n <div class=\"export-body\">${body}</div>\r\n <div class=\"export-ft\">\r\n <span class=\"export-count\">${t('CONFIG.EXPORT_COUNT')} <b>${count}</b></span>\r\n <span class=\"export-ft-actions\">\r\n <button id=\"btn-export-confirm\" class=\"btn-export-confirm\" ${count === 0 ? 'disabled' : ''}>${t('CONFIG.EXPORT_CONFIRM')}</button>\r\n <button id=\"btn-export-cancel\">${t('CONFIG.EXPORT_CANCEL')}</button>\r\n </span>\r\n </div>\r\n </div>\r\n </div>`;\r\n}\r\n\r\nexport function renderConfiguration(state: ConfigurationState, t: (key: string) => string): string {\r\n const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled, startHidden, resumeTtlMinutes } = state;\r\n\r\n const langOptions = LANGS.map(\r\n (l) => `<option value=\"${l.value}\" ${selectedLanguage === l.value ? 'selected' : ''}>${l.label}</option>`,\r\n ).join('');\r\n\r\n return `\r\n <div class=\"cfg-grid\">\r\n\r\n <!-- Language -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.LANG_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.LANG_FIELD')}</span>\r\n <select id=\"lang-select\">${langOptions}</select>\r\n </div>\r\n </div>\r\n\r\n <!-- HTTP Advanced -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.HTTP_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"http-toggle\" ${advancedHttpConfig ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.HTTP_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.HTTP_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Smart Selector -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.SMART_SELECTOR_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"smart-selector-toggle\" ${smartSelectorEnabled ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.SMART_SELECTOR_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.SMART_SELECTOR_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Start Hidden -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.START_HIDDEN_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"start-hidden-toggle\" ${startHidden ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.START_HIDDEN_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.START_HIDDEN_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Recording continuity (cross-app resume TTL) -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.RESUME_TTL_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.RESUME_TTL_LABEL')}</span>\r\n <input type=\"number\" id=\"resume-ttl-input\" min=\"1\" step=\"1\" value=\"${resumeTtlMinutes}\"\r\n style=\"width:80px;padding:5px 8px;background:#161b22;border:1px solid #30363d;border-radius:5px;color:#c9d1d9;font-size:12px;outline:none\" />\r\n </div>\r\n <div class=\"check-sub\" style=\"margin-top:8px\">${t('CONFIG.RESUME_TTL_HINT')}</div>\r\n </div>\r\n\r\n <!-- Selector Strategy -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.SELECTOR_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.SELECTOR_LABEL')}</span>\r\n <select id=\"selector-strategy\">\r\n <option value=\"data-cy\" ${selectorStrategy === 'data-cy' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_DATACY')}</option>\r\n <option value=\"data-testid\" ${selectorStrategy === 'data-testid' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_TESTID')}</option>\r\n <option value=\"aria-label\" ${selectorStrategy === 'aria-label' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_ARIA')}</option>\r\n <option value=\"id\" ${selectorStrategy === 'id' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_ID')}</option>\r\n </select>\r\n </div>\r\n <div class=\"check-sub\" style=\"margin-top:8px\">${t('CONFIG.SELECTOR_HINT')}</div>\r\n </div>\r\n\r\n <!-- Cypress Folder -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.FOLDER_SECTION')}</div>\r\n <div class=\"fs-layout\">\r\n <pre class=\"fs-tree\">cypress/ <span style=\"color:#484f58\">${t('RECORDER.FS_TREE_PICK_HINT')}</span>\r\nβββ e2e/\r\n βββ *.cy.ts</pre>\r\n <div class=\"fs-right\">\r\n <div class=\"fs-status\">\r\n <span class=\"fs-dot ${filesystemGranted ? 'on' : 'off'}\"></span>\r\n ${filesystemGranted && cypressFolderName\r\n ? `<span>${t('CONFIG.FOLDER_CONNECTED')}</span> <span class=\"fs-folder\">π ${escHtml(cypressFolderName)}</span>`\r\n : `<span>${t('CONFIG.FOLDER_NOT_SET')}</span>`}\r\n </div>\r\n <div class=\"btn-row\">\r\n <button id=\"btn-change-folder\">\r\n ${filesystemGranted ? t('CONFIG.FOLDER_CHANGE_BTN') : t('CONFIG.FOLDER_SELECT_BTN')}\r\n </button>\r\n ${filesystemGranted\r\n ? `<button id=\"btn-revoke\" class=\"btn-danger\">${t('CONFIG.FOLDER_REVOKE_BTN')}</button>`\r\n : ''}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Data -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.DATA_SECTION')}</div>\r\n <p class=\"data-desc\">${t('CONFIG.DATA_DESC')}</p>\r\n <div class=\"btn-row\">\r\n <button id=\"btn-export\">${t('CONFIG.EXPORT_BTN')}</button>\r\n <label style=\"cursor:pointer;margin:0\">\r\n <span class=\"btn-import\">${t('CONFIG.IMPORT_BTN')}</span>\r\n <input type=\"file\" class=\"file-input\" id=\"file-input\" accept=\".json\" />\r\n </label>\r\n </div>\r\n </div>\r\n\r\n </div>${renderExportOverlay(state, t)}`;\r\n}\r\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport type { Lang } from '../../models/lang.model';\r\nimport type { SelectorStrategy } from '../../services/recording.service';\r\nimport { RESUME_TTL_CONFIG_KEY, DEFAULT_RESUME_TTL_MINUTES } from '../../models/active-session.model';\r\nimport { showToast } from '../../utils/toast.utils';\r\nimport { selectTestsForExport, type ExportMode } from '../../utils/export-selection.utils';\r\nimport { CONFIGURATION_STYLES } from './configuration.styles';\r\nimport { renderConfiguration } from './configuration.template';\r\n\r\nexport class ConfigurationElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n selectedLanguage = 'es';\r\n advancedHttpConfig = false;\r\n selectorStrategy: SelectorStrategy = 'data-cy';\r\n smartSelectorEnabled = true;\r\n startHidden = false;\r\n resumeTtlMinutes = DEFAULT_RESUME_TTL_MINUTES;\r\n isExporting = false;\r\n exportMode: ExportMode = 'all';\r\n exportTests: TestWithDetails[] = [];\r\n exportSelectedIds: Set<number> = new Set();\r\n exportSelectedTags: Set<string> = new Set();\r\n private filesystemGranted = false;\r\n private cypressFolderName: string | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n this.advancedHttpConfig = localStorage.getItem('extendedHttpCommands') === 'true';\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n this.loadConfig();\r\n this.render();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private async loadConfig(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n if (config?.['language']) {\r\n this.selectedLanguage = config['language'] as string;\r\n this.translation.setLang(this.selectedLanguage as Lang);\r\n }\r\n this.advancedHttpConfig = localStorage.getItem('extendedHttpCommands') === 'true';\r\n this.selectorStrategy = (config?.['selectorStrategy'] as SelectorStrategy) ?? 'data-cy';\r\n this.smartSelectorEnabled = config?.['smartSelectorEnabled'] !== 'false';\r\n this.startHidden = config?.['startHidden'] === 'true';\r\n // Only override when the key exists β otherwise an async load could clobber a\r\n // value just set via onResumeTtlChange (same pattern as `language`).\r\n const ttlRaw = config?.[RESUME_TTL_CONFIG_KEY];\r\n if (ttlRaw !== undefined && ttlRaw !== null) {\r\n const ttl = Number(ttlRaw);\r\n this.resumeTtlMinutes = Number.isFinite(ttl) && ttl > 0 ? ttl : DEFAULT_RESUME_TTL_MINUTES;\r\n }\r\n this.filesystemGranted = config?.['allowReadWriteFiles'] === 'true';\r\n const handle = config?.['cypressDirectoryHandle'] as FileSystemDirectoryHandle | undefined;\r\n this.cypressFolderName = handle?.name ?? null;\r\n this.render();\r\n }\r\n\r\n async onLanguageChange(lang: string): Promise<void> {\r\n this.selectedLanguage = lang;\r\n this.translation.setLang(lang as Lang);\r\n await this.persistence.setConfig({ language: lang });\r\n this.render();\r\n }\r\n\r\n onAdvancedHttpConfigChange(checked: boolean): void {\r\n this.advancedHttpConfig = checked;\r\n localStorage.setItem('extendedHttpCommands', checked ? 'true' : 'false');\r\n this.persistence.setConfig({ extendedHttpCommands: checked ? 'true' : 'false' });\r\n this.render();\r\n }\r\n\r\n async onStartHiddenChange(checked: boolean): Promise<void> {\r\n this.startHidden = checked;\r\n await this.persistence.setConfig({ startHidden: checked ? 'true' : 'false' });\r\n this.dispatchEvent(new CustomEvent('starthiddenchange', { detail: checked, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async onResumeTtlChange(minutes: number): Promise<void> {\r\n const safe = Number.isFinite(minutes) && minutes > 0 ? Math.round(minutes) : DEFAULT_RESUME_TTL_MINUTES;\r\n this.resumeTtlMinutes = safe;\r\n await this.persistence.setConfig({ [RESUME_TTL_CONFIG_KEY]: safe });\r\n this.render();\r\n }\r\n\r\n async onSmartSelectorChange(enabled: boolean): Promise<void> {\r\n this.smartSelectorEnabled = enabled;\r\n await this.persistence.setConfig({ smartSelectorEnabled: enabled ? 'true' : 'false' });\r\n this.dispatchEvent(new CustomEvent('smartselectorchange', { detail: enabled, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async onSelectorStrategyChange(strategy: SelectorStrategy): Promise<void> {\r\n this.selectorStrategy = strategy;\r\n await this.persistence.setConfig({ selectorStrategy: strategy });\r\n this.dispatchEvent(new CustomEvent('selectorstrategychange', { detail: strategy, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async changeFolder(): Promise<void> {\r\n try {\r\n await this.persistence.requestDirectoryPermissions();\r\n await this.loadConfig();\r\n showToast(this.t('CONFIG.FOLDER_UPDATED_TOAST'));\r\n } catch (e: unknown) {\r\n if ((e as DOMException)?.name !== 'AbortError') {\r\n showToast(this.t('CONFIG.FOLDER_ERROR_TOAST'), false);\r\n }\r\n }\r\n }\r\n\r\n async revokeAccess(): Promise<void> {\r\n await this.persistence.setConfig({ allowReadWriteFiles: 'false', cypressDirectoryHandle: null });\r\n this.filesystemGranted = false;\r\n this.cypressFolderName = null;\r\n this.render();\r\n }\r\n\r\n private downloadTests(tests: TestWithDetails[]): void {\r\n const blob = new Blob([JSON.stringify({ tests, interceptors: [] }, null, 2)], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = 'e2e-cypress-export.json';\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n }\r\n\r\n /** Downloads every saved test (used by the \"Todo\" mode and as a direct API). */\r\n async exportAllData(): Promise<void> {\r\n const tests = await this.persistence.getAllTests();\r\n this.downloadTests(tests);\r\n }\r\n\r\n /** Opens the export selection dialog, loading the current tests. */\r\n async openExportDialog(): Promise<void> {\r\n this.exportTests = await this.persistence.getAllTests();\r\n this.exportMode = 'all';\r\n this.exportSelectedIds = new Set();\r\n this.exportSelectedTags = new Set();\r\n this.isExporting = true;\r\n this.render();\r\n }\r\n\r\n cancelExport(): void {\r\n this.isExporting = false;\r\n this.exportSelectedIds.clear();\r\n this.exportSelectedTags.clear();\r\n this.render();\r\n }\r\n\r\n setExportMode(mode: ExportMode): void {\r\n this.exportMode = mode;\r\n this.render();\r\n }\r\n\r\n toggleExportTest(id: number): void {\r\n if (this.exportSelectedIds.has(id)) this.exportSelectedIds.delete(id);\r\n else this.exportSelectedIds.add(id);\r\n this.render();\r\n }\r\n\r\n toggleExportTag(tag: string): void {\r\n if (this.exportSelectedTags.has(tag)) this.exportSelectedTags.delete(tag);\r\n else this.exportSelectedTags.add(tag);\r\n this.render();\r\n }\r\n\r\n /** Downloads the tests resolved by the current mode + selection. No-op if empty. */\r\n confirmExport(): void {\r\n const subset = selectTestsForExport(this.exportTests, this.exportMode, {\r\n ids: this.exportSelectedIds,\r\n tags: this.exportSelectedTags,\r\n });\r\n if (!subset.length) return;\r\n this.downloadTests(subset);\r\n this.isExporting = false;\r\n this.exportSelectedIds.clear();\r\n this.exportSelectedTags.clear();\r\n this.render();\r\n }\r\n\r\n async importAllData(file: File): Promise<void> {\r\n const text = await file.text();\r\n let data: { tests: Record<string, unknown>[]; interceptors: Record<string, unknown>[] };\r\n try {\r\n data = JSON.parse(text);\r\n } catch {\r\n throw new Error(this.t('CONFIG.JSON_INVALID'));\r\n }\r\n if (!data || !Array.isArray(data.tests) || !Array.isArray(data.interceptors)) {\r\n throw new Error(this.t('CONFIG.JSON_BAD_FORMAT'));\r\n }\r\n // Merge: append the imported tests to whatever is already stored β never wipe\r\n // existing data (see docs/specs/004-merge-on-import.md).\r\n await this.persistence.ingestFileData(data.tests, data.interceptors);\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${CONFIGURATION_STYLES}</style>${renderConfiguration({\r\n selectedLanguage: this.selectedLanguage,\r\n advancedHttpConfig: this.advancedHttpConfig,\r\n selectorStrategy: this.selectorStrategy,\r\n filesystemGranted: this.filesystemGranted,\r\n cypressFolderName: this.cypressFolderName,\r\n smartSelectorEnabled: this.smartSelectorEnabled,\r\n startHidden: this.startHidden,\r\n resumeTtlMinutes: this.resumeTtlMinutes,\r\n isExporting: this.isExporting,\r\n exportMode: this.exportMode,\r\n exportTests: this.exportTests,\r\n exportSelectedIds: this.exportSelectedIds,\r\n exportSelectedTags: this.exportSelectedTags,\r\n }, this.t.bind(this))}`;\r\n ;(this.shadow.getElementById('lang-select') as HTMLSelectElement).addEventListener('change', (e) =>\r\n this.onLanguageChange((e.target as HTMLSelectElement).value),\r\n )\r\n ;(this.shadow.getElementById('http-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onAdvancedHttpConfigChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('smart-selector-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onSmartSelectorChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('start-hidden-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onStartHiddenChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('resume-ttl-input') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onResumeTtlChange(Number((e.target as HTMLInputElement).value)),\r\n )\r\n ;(this.shadow.getElementById('selector-strategy') as HTMLSelectElement).addEventListener('change', (e) =>\r\n this.onSelectorStrategyChange((e.target as HTMLSelectElement).value as SelectorStrategy),\r\n );\r\n\r\n this.shadow.getElementById('btn-change-folder')?.addEventListener('click', () => this.changeFolder());\r\n this.shadow.getElementById('btn-revoke')?.addEventListener('click', () => this.revokeAccess());\r\n this.shadow.getElementById('btn-export')?.addEventListener('click', () => this.openExportDialog());\r\n\r\n this.shadow.getElementById('btn-export-confirm')?.addEventListener('click', () => this.confirmExport());\r\n this.shadow.getElementById('btn-export-cancel')?.addEventListener('click', () => this.cancelExport());\r\n this.shadow.querySelectorAll('[data-export-mode]').forEach((el) =>\r\n el.addEventListener('click', () => this.setExportMode((el as HTMLElement).dataset['exportMode'] as ExportMode)),\r\n );\r\n this.shadow.querySelectorAll('[data-export-test]').forEach((el) =>\r\n el.addEventListener('change', () => this.toggleExportTest(Number((el as HTMLElement).dataset['exportTest']))),\r\n );\r\n this.shadow.querySelectorAll('[data-export-tag]').forEach((el) =>\r\n el.addEventListener('click', () => this.toggleExportTag((el as HTMLElement).dataset['exportTag'] ?? '')),\r\n )\r\n ;(this.shadow.getElementById('file-input') as HTMLInputElement).addEventListener('change', async (e) => {\r\n const file = (e.target as HTMLInputElement).files?.[0];\r\n if (!file) return;\r\n try {\r\n await this.importAllData(file);\r\n alert(this.t('CONFIG.IMPORT_SUCCESS'));\r\n } catch (err: unknown) {\r\n alert((err as Error).message ?? this.t('CONFIG.IMPORT_ERROR'));\r\n }\r\n const target = e.target as HTMLInputElement | null;\r\n if (target) target.value = '';\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('e2e-configuration')) {\r\n customElements.define('e2e-configuration', ConfigurationElement);\r\n}\r\n","export const ADVANCED_TEST_EDITOR_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .layout { display: flex; flex: 1; min-height: 0; }\n .sidebar {\n border-right: none; display: flex; flex-direction: column;\n background: #0d1117; flex-shrink: 0; min-width: 140px; max-width: 500px;\n }\n .tree-scroll {\n flex: 1; overflow-y: auto; padding: 6px 4px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .tree-scroll::-webkit-scrollbar { width: 4px; }\n .tree-scroll::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .resize-handle {\n width: 4px; background: #21262d; cursor: col-resize; flex-shrink: 0;\n transition: background 0.15s;\n }\n .resize-handle:hover, .resize-handle.dragging { background: #2f81f7; }\n .main { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #161b22; min-width: 0; }\n .no-perm {\n padding: 28px; color: #484f58; font-size: 13px; text-align: center;\n display: flex; flex-direction: column; align-items: center; gap: 12px; line-height: 1.6;\n }\n .tree-item {\n padding: 4px 6px; border-radius: 4px; cursor: pointer;\n font-size: 12px; color: #8b949e; white-space: nowrap;\n overflow: hidden; text-overflow: ellipsis;\n transition: background 0.12s, color 0.12s;\n display: flex; align-items: center; gap: 4px; user-select: none;\n }\n .tree-item:hover { background: #161b22; color: #c9d1d9; }\n .tree-item.selected { background: rgba(47,129,247,0.12); color: #2f81f7; }\n .tree-item.dir { color: #e3b341; font-weight: 600; }\n .tree-item.dir:hover { background: rgba(227,179,65,0.08); color: #f0c040; }\n .dir-arrow { font-size: 8px; color: #484f58; width: 10px; flex-shrink: 0; line-height: 1; }\n .tree-connector { display: block; width: 1px; background: #21262d; margin-left: 13px; height: 100%; }\n .content-area {\n flex: 1; padding: 12px 14px; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .content-area::-webkit-scrollbar { width: 4px; }\n .content-area::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .file-name { font-size: 11px; color: #484f58; margin-bottom: 8px; font-family: monospace; }\n pre {\n background: #0d1117; padding: 12px; border-radius: 8px;\n font-size: 11px; color: #c9d1d9; margin: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n line-height: 1.7; border: 1px solid #21262d;\n white-space: pre; overflow-x: auto; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n pre::-webkit-scrollbar { width: 4px; height: 4px; }\n pre::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .pre-block { font-size: 10.5px; }\n .pre-icp .sh-str { color: #85e89d; }\n .sh-kw { color: #ff7b72; }\n .sh-bi { color: #d2a8ff; }\n .sh-str { color: #a5d6ff; }\n .sh-cmt { color: #8b949e; font-style: italic; }\n .sh-num { color: #79c0ff; }\n .footer {\n padding: 10px 14px; border-top: 1px solid #21262d;\n display: flex; gap: 8px; justify-content: flex-end; background: #161b22;\n }\n button {\n padding: 6px 16px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n button:disabled { opacity: 0.35; cursor: default; }\n .btn-save { background: #2f81f7; border-color: #2f81f7; color: #fff; }\n .btn-save:hover { background: #1f6feb; border-color: #1f6feb; color: #fff; }\n .btn-save:disabled { background: #21262d; border-color: #30363d; color: #8b949e; }\n .placeholder { color: #484f58; font-size: 13px; padding: 28px; text-align: center; }\n .test-notes {\n margin: 0 0 10px; padding: 8px 12px;\n background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);\n border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;\n line-height: 1.6; white-space: pre-wrap; word-break: break-word;\n }\n .block-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }\n .btn-copy {\n padding: 3px 10px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-copy:hover { background: #30363d; color: #e6edf3; }\n .sidebar-toolbar {\n display: flex; flex-wrap: wrap; gap: 4px; padding: 6px 6px 4px;\n border-bottom: 1px solid #21262d; flex-shrink: 0; background: #0d1117;\n }\n .btn-toolbar {\n flex: 1 1 calc(50% - 2px); padding: 4px 6px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #161b22; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; overflow: hidden;\n text-overflow: ellipsis;\n }\n .btn-toolbar.btn-full { flex: 1 1 100%; }\n .btn-toolbar:hover { background: #30363d; color: #e6edf3; }\n .btn-toolbar.btn-new { color: #3fb950; border-color: #238636; }\n .btn-toolbar.btn-new:hover { background: #238636; color: #fff; }\n .btn-toolbar.btn-new-folder { color: #d29922; border-color: #9e6a03; }\n .btn-toolbar.btn-new-folder:hover { background: #9e6a03; color: #fff; }\n .new-file-form {\n padding: 6px; border-bottom: 1px solid #21262d; display: flex; flex-direction: column; gap: 4px;\n }\n .new-file-form input {\n width: 100%; padding: 4px 7px; background: #0d1117; border: 1px solid #30363d;\n border-radius: 5px; color: #e6edf3; font-size: 11px; font-family: monospace;\n outline: none;\n }\n .new-file-form input:focus { border-color: #2f81f7; }\n .new-file-form .ext { font-size: 9px; color: #484f58; padding: 0 2px; }\n .new-file-actions { display: flex; gap: 4px; }\n .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; }\n .btn-confirm:hover { background: #2ea043; }\n .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; }\n .btn-cancel-form:hover { background: #30363d; color: #e6edf3; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\nimport { syntaxHighlight } from '../../utils/syntax-highlight.utils';\nimport type { DirectoryNode, FileNode } from '../../services/advanced-test.transformation.service';\n\nexport interface AdvancedEditorState {\n e2eTree: Array<DirectoryNode | FileNode>;\n selectedFile: unknown;\n selectedFileContent: string | null;\n testItBlock: string;\n interceptorsBlock: string;\n testNotes: string;\n saveButtonEnabled: boolean;\n isCreatingFile: boolean;\n isCreatingFolder: boolean;\n collapsedDirs: Set<string>;\n sidebarWidth: number;\n}\n\nexport function renderNoPermission(needsReauth: boolean, t: (key: string) => string): string {\n const reauthBtn = needsReauth\n ? `<button id=\"btn-reauth\"\n style=\"margin-top:14px;padding:7px 16px;border:none;border-radius:6px;cursor:pointer;\n font-size:12px;font-weight:500;background:#2f81f7;color:#fff\">\n ${t('ADVANCED_EDITOR.REAUTH_BTN')}\n </button>`\n : '';\n\n return `\n <div class=\"no-perm\">\n <div>${needsReauth ? t('ADVANCED_EDITOR.PERMISSION_EXPIRED') : t('ADVANCED_EDITOR.NO_ACCESS')}</div>\n <div style=\"font-size:11px\">${needsReauth\n ? t('ADVANCED_EDITOR.PERMISSION_EXPIRED_HINT')\n : t('ADVANCED_EDITOR.NO_ACCESS_HINT')}</div>\n ${reauthBtn}\n </div>`;\n}\n\nexport function renderAdvancedEditor(state: AdvancedEditorState, t: (key: string) => string): string {\n const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, testNotes, saveButtonEnabled, isCreatingFile, isCreatingFolder, collapsedDirs, sidebarWidth } = state;\n\n const treeHtml = e2eTree.length\n ? renderTree(e2eTree, selectedFile, collapsedDirs)\n : `<div class=\"tree-item\" style=\"color:#6c7a99\">${t('ADVANCED_EDITOR.NO_FILES')}</div>`;\n\n const contentHtml = selectedFileContent\n ? `<div class=\"file-name\">π ${escHtml((selectedFile as { name?: string } | null)?.name ?? '')}</div>\n <pre class=\"pre-file\">${syntaxHighlight(selectedFileContent.slice(0, 6000))}${selectedFileContent.length > 6000 ? '\\n...' : ''}</pre>`\n : `<div class=\"placeholder\">${t('ADVANCED_EDITOR.SELECT_FILE')}</div>`;\n\n const notesHtml = (testItBlock && testNotes)\n ? `<p class=\"test-notes\">${escHtml(testNotes)}</p>`\n : '';\n\n const itHtml = testItBlock\n ? `<div style=\"margin-top:10px\">\n <div class=\"file-name block-header\">\n <span>${t('ADVANCED_EDITOR.IT_LABEL')}</span>\n <button id=\"btn-copy-it\" class=\"btn-copy\">${t('ADVANCED_EDITOR.COPY_IT_BTN')}</button>\n </div>\n <pre class=\"pre-block\">${syntaxHighlight(testItBlock.slice(0, 3000))}</pre>\n </div>` : '';\n\n const interceptorsHtml = interceptorsBlock\n ? `<div style=\"margin-top:10px\">\n <div class=\"file-name block-header\">\n <span>${t('ADVANCED_EDITOR.BEFORE_EACH_LABEL')}</span>\n <button id=\"btn-copy-interceptors\" class=\"btn-copy\">${t('ADVANCED_EDITOR.COPY_ICP_BTN')}</button>\n </div>\n <pre class=\"pre-block pre-icp\">${syntaxHighlight(interceptorsBlock.slice(0, 3000))}</pre>\n </div>` : '';\n\n const newFileForm = isCreatingFile\n ? `<div class=\"new-file-form\">\n <input id=\"input-new-file\" type=\"text\" placeholder=\"${escHtml(t('ADVANCED_EDITOR.NEW_FILE_PLACEHOLDER'))}\" autocomplete=\"off\" />\n <span class=\"ext\">.cy.ts</span>\n <div class=\"new-file-actions\">\n <button id=\"btn-new-file-confirm\" class=\"btn-confirm\">${t('ADVANCED_EDITOR.NEW_FILE_CONFIRM')}</button>\n <button id=\"btn-new-file-cancel\" class=\"btn-cancel-form\">${t('ADVANCED_EDITOR.NEW_FILE_CANCEL')}</button>\n </div>\n </div>`\n : '';\n\n const newFolderForm = isCreatingFolder\n ? `<div class=\"new-file-form\">\n <input id=\"input-new-folder\" type=\"text\" placeholder=\"${escHtml(t('ADVANCED_EDITOR.NEW_FOLDER_PLACEHOLDER'))}\" autocomplete=\"off\" />\n <div class=\"new-file-actions\">\n <button id=\"btn-new-folder-confirm\" class=\"btn-confirm\">${t('ADVANCED_EDITOR.NEW_FILE_CONFIRM')}</button>\n <button id=\"btn-new-folder-cancel\" class=\"btn-cancel-form\">${t('ADVANCED_EDITOR.NEW_FILE_CANCEL')}</button>\n </div>\n </div>`\n : '';\n\n const toolbar = `\n <div class=\"sidebar-toolbar\">\n <button id=\"btn-new-file\" class=\"btn-toolbar btn-new\">${t('ADVANCED_EDITOR.NEW_FILE_BTN')}</button>\n <button id=\"btn-new-folder\" class=\"btn-toolbar btn-new-folder\">${t('ADVANCED_EDITOR.NEW_FOLDER_BTN')}</button>\n <button id=\"btn-refresh\" class=\"btn-toolbar btn-full\">${t('ADVANCED_EDITOR.REFRESH_BTN')}</button>\n </div>`;\n\n return `\n <div class=\"layout\">\n <div class=\"sidebar\" style=\"width:${sidebarWidth}px\">\n ${toolbar}\n ${newFileForm}\n ${newFolderForm}\n <div class=\"tree-scroll\">${treeHtml}</div>\n </div>\n <div id=\"resize-handle\" class=\"resize-handle\"></div>\n <div class=\"main\">\n <div class=\"content-area\">${contentHtml}${notesHtml}${itHtml}${interceptorsHtml}</div>\n <div class=\"footer\">\n <button id=\"btn-save\" class=\"btn-save\"\n ${!saveButtonEnabled || !testItBlock ? 'disabled' : ''}>\n ${t('ADVANCED_EDITOR.INSERT_BTN')}\n </button>\n <button id=\"btn-edit\" ${!saveButtonEnabled ? 'disabled' : ''}>\n ${t('ADVANCED_EDITOR.EDIT_MANUAL_BTN')}\n </button>\n <button id=\"btn-close\">${t('ADVANCED_EDITOR.CLOSE_BTN')}</button>\n </div>\n </div>\n </div>`;\n}\n\nexport function renderTree(\n nodes: Array<DirectoryNode | FileNode>,\n selected: unknown,\n collapsedDirs: Set<string>,\n indent = 0,\n parentPath = '',\n): string {\n return nodes.map((n) => {\n const currentPath = parentPath ? `${parentPath}/${n.name}` : n.name;\n const isFile = n.kind === 'file';\n const pad = `padding-left:${6 + indent * 14}px`;\n\n if (!isFile) {\n const dir = n as DirectoryNode;\n const hasChildren = (dir.children?.length ?? 0) > 0;\n const isCollapsed = collapsedDirs.has(currentPath);\n const arrow = hasChildren ? (isCollapsed ? 'βΆ' : 'βΌ') : 'Β·';\n const dirHtml = `<div class=\"tree-item dir\" style=\"${pad}\" data-dir-path=\"${escAttr(currentPath)}\">\n <span class=\"dir-arrow\">${arrow}</span>π ${escHtml(n.name)}\n </div>`;\n if (!hasChildren || isCollapsed) return dirHtml;\n return dirHtml + renderTree(dir.children, selected, collapsedDirs, indent + 1, currentPath);\n }\n\n const isSel = (selected as { name?: string } | null)?.name === n.name;\n const cls = `tree-item${isSel ? ' selected' : ''}`;\n const data = JSON.stringify({ kind: n.kind, name: n.name }).replace(/\"/g, '"');\n return `<div class=\"${cls}\" style=\"${pad}\" data-file=\"${data}\">π ${escHtml(n.name)}</div>`;\n }).join('');\n}\n\nexport async function findFileHandleRecursive(\n dir: FileSystemDirectoryHandle,\n name: string,\n): Promise<FileSystemFileHandle | null> {\n for await (const entry of dir.values()) {\n if (entry.kind === 'file' && entry.name === name) return entry as FileSystemFileHandle;\n if (entry.kind === 'directory') {\n const found = await findFileHandleRecursive(entry as FileSystemDirectoryHandle, name);\n if (found) return found;\n }\n }\n return null;\n}\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport { AdvancedTestTransformationService } from '../../services/advanced-test.transformation.service';\r\nimport { escapeSingleQuotes } from '../../utils/code-format.utils';\r\nimport { ADVANCED_TEST_EDITOR_STYLES } from './advanced-test-editor.styles';\r\nimport { renderNoPermission, renderAdvancedEditor, findFileHandleRecursive } from './advanced-test-editor.template';\r\nimport type { DirectoryNode, FileNode } from '../../services/advanced-test.transformation.service';\r\n\r\nexport class AdvancedTestEditorElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private readonly transformationService = new AdvancedTestTransformationService();\r\n\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n testId?: number;\r\n\r\n e2eTree: Array<DirectoryNode | FileNode> = [];\r\n selectedFile: unknown = null;\r\n saveButtonEnabled = false;\r\n selectedFileHandle: FileSystemFileHandle | null = null;\r\n selectedFileContent: string | null = null;\r\n testItBlock = '';\r\n interceptorsBlock = '';\r\n testNotes = '';\r\n isPreviewMode = false;\r\n previewFileName: string | null = null;\r\n previewFileContent: string | null = null;\r\n isCreatingFile = false;\r\n isCreatingFolder = false;\r\n collapsedDirs: Set<string> = new Set();\r\n sidebarWidth = 220;\r\n private hasPermission = false;\r\n private needsReauth = false;\r\n private _dirHandle: FileSystemDirectoryHandle | null = null;\r\n private _e2eHandle: FileSystemDirectoryHandle | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n this.init();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private async init(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n const allowed = config?.['allowReadWriteFiles'] === 'true';\r\n\r\n if (!allowed) {\r\n this.hasPermission = false;\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n this.render();\r\n return;\r\n }\r\n\r\n const handle = config?.['cypressDirectoryHandle'] as FileSystemDirectoryHandle | null;\r\n if (!handle) {\r\n this.hasPermission = false;\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n this.render();\r\n return;\r\n }\r\n\r\n // queryPermission does NOT require a user gesture\r\n const perm = await (handle as unknown as FileSystemHandleWithPermission).queryPermission({ mode: 'readwrite' });\r\n this._dirHandle = handle;\r\n this.hasPermission = perm === 'granted';\r\n this.needsReauth = perm === 'prompt';\r\n\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n if (this.hasPermission) await this.getFoldersData();\r\n this.render();\r\n }\r\n\r\n async getFoldersData(): Promise<void> {\r\n if (!this.hasPermission || !this._dirHandle) return;\r\n try {\r\n for await (const entry of this._dirHandle.values()) {\r\n if (entry.kind === 'directory' && entry.name === 'e2e') {\r\n this._e2eHandle = entry as FileSystemDirectoryHandle;\r\n const tree = await this.transformationService.scanDirectory(this._e2eHandle);\r\n this.e2eTree = tree.children ?? [];\r\n this.render();\r\n return;\r\n }\r\n }\r\n } catch { /* silently skip permission errors */ }\r\n }\r\n\r\n async createNewFile(rawName: string): Promise<void> {\r\n if (!this._e2eHandle) return;\r\n const name = rawName.trim().replace(/\\.cy\\.ts$/, '');\r\n if (!name) return;\r\n const fileName = `${name}.cy.ts`;\r\n const template = `describe('${escapeSingleQuotes(name)}', () => {\\n\\n it('should ', () => {\\n\\n });\\n\\n});\\n`;\r\n try {\r\n const fileHandle = await this._e2eHandle.getFileHandle(fileName, { create: true });\r\n const writable = await fileHandle.createWritable();\r\n await writable.write(template);\r\n await writable.close();\r\n } catch { /* silently ignore if file already exists or permission denied */ }\r\n this.isCreatingFile = false;\r\n await this.getFoldersData();\r\n }\r\n\r\n async createNewFolder(rawName: string): Promise<void> {\r\n if (!this._e2eHandle) return;\r\n const name = rawName.trim().replace(/[/\\\\]/g, '');\r\n if (!name) return;\r\n try {\r\n await this._e2eHandle.getDirectoryHandle(name, { create: true });\r\n } catch { /* silently ignore if folder already exists or permission denied */ }\r\n this.isCreatingFolder = false;\r\n await this.getFoldersData();\r\n }\r\n\r\n async refreshTree(): Promise<void> {\r\n await this.getFoldersData();\r\n }\r\n\r\n async saveCommandsToFile(): Promise<void> {\r\n if (!this.selectedFileHandle || !this.selectedFileContent || !this.testItBlock) return;\r\n let content = this.selectedFileContent;\r\n if (this.interceptorsBlock) {\r\n content = this.transformationService.insertBeforeEach(content, this.interceptorsBlock);\r\n }\r\n const comment = this.testNotes ? this.transformationService.buildBlockComment(this.testNotes) + '\\n' : '';\r\n content = this.transformationService.insertItBlock(content, comment + this.testItBlock);\r\n if (!content) return;\r\n const writable = await this.selectedFileHandle.createWritable();\r\n await writable.write(content);\r\n await writable.close();\r\n this.dispatchEvent(new CustomEvent('closemodal', { bubbles: true, composed: true }));\r\n }\r\n\r\n async onFileClick(file: unknown): Promise<void> {\r\n if (!this.transformationService.isFile(file)) return;\r\n this.selectedFile = file;\r\n this.saveButtonEnabled = true;\r\n\r\n if (!this._dirHandle) return;\r\n const handle = await findFileHandleRecursive(this._dirHandle, (file as { name: string }).name);\r\n if (!handle) return;\r\n this.selectedFileHandle = handle;\r\n const fileObj = await handle.getFile();\r\n this.selectedFileContent = await fileObj.text();\r\n this.render();\r\n }\r\n\r\n markFileAsSelected(file: unknown): void {\r\n this.selectedFile = file;\r\n }\r\n\r\n async loadCypressCommandsForTest(testId: number): Promise<void> {\r\n const test = await this.persistence.getTestById(testId);\r\n if (test) {\r\n this.testItBlock = test.itBlock ?? '';\r\n this.interceptorsBlock = test.interceptorsBlock ?? '';\r\n this.testNotes = test.notes ?? '';\r\n } else {\r\n this.testItBlock = '';\r\n this.interceptorsBlock = '';\r\n this.testNotes = '';\r\n }\r\n this.render();\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n openEditManually(): void {\r\n if (!this.selectedFileHandle || !this.selectedFileContent) return;\r\n this.dispatchEvent(new CustomEvent('openfileeditor', {\r\n detail: {\r\n handle: this.selectedFileHandle,\r\n content: this.selectedFileContent,\r\n fileName: (this.selectedFile as { name?: string } | null)?.name ?? '',\r\n testId: this.testId,\r\n itBlock: this.testItBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n notes: this.testNotes,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n }\r\n\r\n toggleDir(path: string): void {\r\n if (this.collapsedDirs.has(path)) {\r\n this.collapsedDirs.delete(path);\r\n } else {\r\n this.collapsedDirs.add(path);\r\n }\r\n this.render();\r\n }\r\n\r\n private setupResizeHandle(): void {\r\n const handle = this.shadow.getElementById('resize-handle');\r\n const sidebar = this.shadow.querySelector('.sidebar') as HTMLElement | null;\r\n if (!handle || !sidebar) return;\r\n\r\n let startX = 0;\r\n let startWidth = 0;\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n const delta = e.clientX - startX;\r\n const newWidth = Math.max(140, Math.min(500, startWidth + delta));\r\n this.sidebarWidth = newWidth;\r\n sidebar.style.width = `${newWidth}px`;\r\n };\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n handle.classList.remove('dragging');\r\n };\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n startX = e.clientX;\r\n startWidth = sidebar.offsetWidth;\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n document.body.style.cursor = 'col-resize';\r\n document.body.style.userSelect = 'none';\r\n handle.classList.add('dragging');\r\n e.preventDefault();\r\n });\r\n }\r\n\r\n closePreview(): void {\r\n this.isPreviewMode = false;\r\n this.previewFileName = null;\r\n this.previewFileContent = null;\r\n if (this.testId !== undefined) {\r\n this.dispatchEvent(new CustomEvent('closemodal', { bubbles: true, composed: true }));\r\n }\r\n this.render();\r\n }\r\n\r\n private render(): void {\r\n if (!this.hasPermission) {\r\n this.shadow.innerHTML = `<style>${ADVANCED_TEST_EDITOR_STYLES}</style>${renderNoPermission(this.needsReauth, this.t.bind(this))}`;\r\n\r\n this.shadow.getElementById('btn-reauth')?.addEventListener('click', async () => {\r\n if (!this._dirHandle) return;\r\n const perm = await (this._dirHandle as unknown as FileSystemHandleWithPermission).requestPermission({ mode: 'readwrite' });\r\n if (perm === 'granted') {\r\n this.hasPermission = true;\r\n this.needsReauth = false;\r\n await this.getFoldersData();\r\n this.render();\r\n }\r\n });\r\n return;\r\n }\r\n\r\n this.shadow.innerHTML = `<style>${ADVANCED_TEST_EDITOR_STYLES}</style>${renderAdvancedEditor({\r\n e2eTree: this.e2eTree,\r\n selectedFile: this.selectedFile,\r\n selectedFileContent: this.selectedFileContent,\r\n testItBlock: this.testItBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n testNotes: this.testNotes,\r\n saveButtonEnabled: this.saveButtonEnabled,\r\n isCreatingFile: this.isCreatingFile,\r\n isCreatingFolder: this.isCreatingFolder,\r\n collapsedDirs: this.collapsedDirs,\r\n sidebarWidth: this.sidebarWidth,\r\n }, this.t.bind(this))}`;\r\n\r\n this.shadow.querySelectorAll('[data-file]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const data = (el as HTMLElement).dataset['file'];\r\n if (data) this.onFileClick(JSON.parse(data));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-dir-path]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const path = (el as HTMLElement).dataset['dirPath'];\r\n if (path) this.toggleDir(path);\r\n });\r\n });\r\n this.setupResizeHandle();\r\n this.shadow.getElementById('btn-save')\r\n ?.addEventListener('click', () => this.saveCommandsToFile());\r\n this.shadow.getElementById('btn-edit')\r\n ?.addEventListener('click', () => this.openEditManually());\r\n this.shadow.getElementById('btn-copy-it')\r\n ?.addEventListener('click', () => this.copyToClipboard(this.testItBlock));\r\n this.shadow.getElementById('btn-copy-interceptors')\r\n ?.addEventListener('click', () => this.copyToClipboard(this.interceptorsBlock));\r\n this.shadow.getElementById('btn-close')\r\n ?.addEventListener('click', () => this.closePreview());\r\n this.shadow.getElementById('btn-new-file')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFile = !this.isCreatingFile;\r\n this.isCreatingFolder = false;\r\n this.render();\r\n if (this.isCreatingFile) this.shadow.getElementById('input-new-file')?.focus();\r\n });\r\n this.shadow.getElementById('btn-new-folder')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFolder = !this.isCreatingFolder;\r\n this.isCreatingFile = false;\r\n this.render();\r\n if (this.isCreatingFolder) this.shadow.getElementById('input-new-folder')?.focus();\r\n });\r\n this.shadow.getElementById('btn-refresh')\r\n ?.addEventListener('click', () => this.refreshTree());\r\n this.shadow.getElementById('btn-new-file-confirm')\r\n ?.addEventListener('click', () => {\r\n const input = this.shadow.getElementById('input-new-file') as HTMLInputElement | null;\r\n this.createNewFile(input?.value ?? '');\r\n });\r\n this.shadow.getElementById('btn-new-file-cancel')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFile = false;\r\n this.render();\r\n });\r\n const input = this.shadow.getElementById('input-new-file') as HTMLInputElement | null;\r\n input?.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n this.createNewFile(input.value);\r\n } else if (e.key === 'Escape') {\r\n this.isCreatingFile = false;\r\n this.render();\r\n }\r\n });\r\n this.shadow.getElementById('btn-new-folder-confirm')\r\n ?.addEventListener('click', () => {\r\n const folderInput = this.shadow.getElementById('input-new-folder') as HTMLInputElement | null;\r\n this.createNewFolder(folderInput?.value ?? '');\r\n });\r\n this.shadow.getElementById('btn-new-folder-cancel')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFolder = false;\r\n this.render();\r\n });\r\n const folderInput = this.shadow.getElementById('input-new-folder') as HTMLInputElement | null;\r\n folderInput?.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n this.createNewFolder(folderInput.value);\r\n } else if (e.key === 'Escape') {\r\n this.isCreatingFolder = false;\r\n this.render();\r\n }\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('advanced-test-editor')) {\r\n customElements.define('advanced-test-editor', AdvancedTestEditorElement);\r\n}\r\n","export const FILE_PREVIEW_STYLES = `\n :host { display: block; height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n .container { display: flex; flex-direction: column; height: 100%; }\n .header {\n display: flex; align-items: center; gap: 8px;\n padding: 8px 12px; border-bottom: 1px solid #21262d;\n background: #161b22;\n }\n .file-name { flex: 1; font-size: 12px; color: #8b949e;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; }\n .body { display: flex; flex: 1; overflow: hidden; min-height: 0; }\n .editor {\n flex: 1; min-width: 0; padding: 14px;\n background: #0d1117; color: #c9d1d9; border: none; outline: none;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 12px;\n line-height: 1.7; resize: none;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .editor::-webkit-scrollbar { width: 5px; }\n .editor::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }\n .blocks-panel {\n width: 260px; flex-shrink: 0; border-left: 1px solid #21262d;\n background: #0d1117; padding: 10px 12px; overflow-y: auto;\n display: flex; flex-direction: column; gap: 10px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .blocks-panel::-webkit-scrollbar { width: 4px; }\n .blocks-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .block-section { display: flex; flex-direction: column; gap: 4px; }\n .block-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2px; }\n .block-label { font-size: 10px; color: #484f58; text-transform: uppercase; letter-spacing: 0.6px; font-weight: 600; }\n .btn-copy-sm {\n padding: 2px 8px; border: 1px solid #30363d; border-radius: 4px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap;\n }\n .btn-copy-sm:hover { background: #30363d; color: #e6edf3; }\n .block-pre {\n margin: 0; padding: 6px 8px; background: #161b22;\n border-radius: 5px; border: 1px solid #21262d;\n font-size: 10px; color: #c9d1d9; line-height: 1.6;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n max-height: 280px; overflow-y: auto; white-space: pre-wrap; word-break: break-all;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .diff-panel {\n flex: 1; overflow-y: auto; background: #0d1117; border-left: 1px solid #21262d;\n padding: 8px 0; min-width: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 11px;\n line-height: 1.6;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .diff-panel::-webkit-scrollbar { width: 5px; }\n .diff-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }\n .diff-line {\n display: flex; gap: 0; white-space: pre; padding: 0 12px;\n }\n .diff-line.added { background: rgba(63,185,80,0.12); color: #3fb950; }\n .diff-line.removed { background: rgba(248,81,73,0.1); color: #f85149; }\n .diff-line.same { color: #484f58; }\n .diff-sign { width: 14px; flex-shrink: 0; user-select: none; }\n .diff-empty { color: #484f58; font-size: 12px; padding: 20px; text-align: center; }\n .footer {\n display: flex; gap: 8px; padding: 8px 12px;\n border-top: 1px solid #21262d; justify-content: flex-end;\n background: #161b22;\n }\n button {\n padding: 6px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n .btn-save { background: #3fb950; border-color: #3fb950; color: #fff; }\n .btn-save:hover { background: #2ea043; border-color: #2ea043; }\n .btn-launch { background: transparent; border-color: #e3b341; color: #e3b341; }\n .btn-launch:hover { background: rgba(227,179,65,0.1); }\n .btn-launch:disabled { opacity: 0.45; cursor: not-allowed; }\n .btn-launch:disabled:hover { background: transparent; }\n .launch-hint { font-size: 10px; color: #8b6d3b; align-self: center; }\n .btn-insert { background: transparent; border-color: #a371f7; color: #a371f7; }\n .btn-insert:hover { background: rgba(163,113,247,0.12); color: #c8a8ff; }\n .btn-diff-active { background: rgba(47,129,247,0.15); border-color: rgba(47,129,247,0.4); color: #2f81f7; }\n\n /* ββ Run result panel βββββββββββββββββββββββββββββββββββ */\n .run-result {\n border-top: 1px solid #21262d; padding: 8px 12px; background: #0d1117;\n max-height: 220px; overflow-y: auto; flex-shrink: 0;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .run-status { font-size: 12px; font-weight: 600; }\n .run-passed .run-status { color: #3fb950; }\n .run-failed .run-status { color: #f85149; }\n .run-running .run-status { color: #e3b341; }\n .run-error .run-status { color: #f85149; }\n .run-output {\n margin: 6px 0 0; padding: 8px 10px; background: #161b22; border: 1px solid #21262d;\n border-radius: 5px; font-size: 10px; color: #c9d1d9; line-height: 1.5;\n font-family: 'Cascadia Code','Fira Code','Consolas',monospace;\n white-space: pre-wrap; word-break: break-word; max-height: 160px; overflow-y: auto;\n }\n`;\n","import { escHtml } from '../../utils/html.utils';\n\nexport type DiffEntry = { type: 'same' | 'added' | 'removed'; line: string };\n\nexport function computeDiff(original: string, modified: string): DiffEntry[] {\n const MAX_LINES = 600;\n const a = original.split('\\n').slice(0, MAX_LINES);\n const b = modified.split('\\n').slice(0, MAX_LINES);\n const m = a.length, n = b.length;\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n\n const result: DiffEntry[] = [];\n let i = m, j = n;\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {\n result.unshift({ type: 'same', line: a[i - 1] });\n i--; j--;\n } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {\n result.unshift({ type: 'added', line: b[j - 1] });\n j--;\n } else {\n result.unshift({ type: 'removed', line: a[i - 1] });\n i--;\n }\n }\n return result;\n}\n\nexport function buildDiffHtml(original: string, current: string, t: (key: string) => string): string {\n if (original === current) return `<div class=\"diff-empty\">${t('FILE_PREVIEW.NO_CHANGES')}</div>`;\n\n const diff = computeDiff(original, current);\n if (!diff.length) return `<div class=\"diff-empty\">${t('FILE_PREVIEW.NO_CHANGES_SHORT')}</div>`;\n\n const CONTEXT = 2;\n const compressed: DiffEntry[] = [];\n let sameRun = 0;\n for (let idx = 0; idx < diff.length; idx++) {\n if (diff[idx].type === 'same') {\n sameRun++;\n if (sameRun <= CONTEXT) compressed.push(diff[idx]);\n else if (idx + 1 < diff.length && diff[idx + 1].type !== 'same') {\n if (sameRun > CONTEXT * 2) compressed.push({ type: 'same', line: 'β¦' });\n compressed.push(diff[idx]);\n }\n } else {\n sameRun = 0;\n compressed.push(diff[idx]);\n }\n }\n\n return compressed.map(({ type, line }) => {\n const sign = type === 'added' ? '+' : type === 'removed' ? 'β' : ' ';\n return `<div class=\"diff-line ${type}\"><span class=\"diff-sign\">${sign}</span><span>${escHtml(line)}</span></div>`;\n }).join('');\n}\n\nexport type RunState = 'idle' | 'running' | 'passed' | 'failed' | 'error';\n\nexport interface FilePreviewState {\n fileName: string | null;\n showDiff: boolean;\n fileContent: string | null;\n originalContent: string | null;\n currentContent: string;\n itBlock: string;\n interceptorsBlock: string;\n closeLabel: string;\n isLocal: boolean;\n runState: RunState;\n runOutput: string;\n}\n\nconst RUN_STATUS_KEY: Record<Exclude<RunState, 'idle'>, string> = {\n running: 'FILE_PREVIEW.LAUNCH_RUNNING',\n passed: 'FILE_PREVIEW.LAUNCH_PASSED',\n failed: 'FILE_PREVIEW.LAUNCH_FAILED',\n error: 'FILE_PREVIEW.LAUNCH_NO_RUNNER',\n};\n\nexport function renderFilePreview(state: FilePreviewState, t: (key: string) => string): string {\n const { fileName, showDiff, fileContent, originalContent, currentContent, itBlock, interceptorsBlock, closeLabel, isLocal, runState, runOutput } = state;\n\n const blocksPanelHtml = (itBlock || interceptorsBlock) ? `\n <div class=\"blocks-panel\">\n ${itBlock ? `\n <div class=\"block-section\">\n <div class=\"block-row\">\n <span class=\"block-label\">${t('FILE_PREVIEW.BLOCK_IT')}</span>\n <button id=\"btn-copy-it\" class=\"btn-copy-sm\">${t('FILE_PREVIEW.COPY_BTN')}</button>\n </div>\n <pre class=\"block-pre\">${escHtml(itBlock.slice(0, 2000))}</pre>\n </div>` : ''}\n ${interceptorsBlock ? `\n <div class=\"block-section\">\n <div class=\"block-row\">\n <span class=\"block-label\">${t('FILE_PREVIEW.BLOCK_BEFORE_EACH')}</span>\n <button id=\"btn-copy-icp\" class=\"btn-copy-sm\">${t('FILE_PREVIEW.COPY_BTN')}</button>\n </div>\n <pre class=\"block-pre\" style=\"color:#3fb950\">${escHtml(interceptorsBlock.slice(0, 2000))}</pre>\n </div>` : ''}\n </div>` : '';\n\n const hasChanges = originalContent !== null && originalContent !== (fileContent ?? '');\n const hasBlocks = !!(itBlock || interceptorsBlock);\n\n const launchBtnHtml = isLocal\n ? `<button id=\"btn-launch\" class=\"btn-launch\" ${runState === 'running' ? 'disabled' : ''}>${runState === 'running' ? t('FILE_PREVIEW.LAUNCH_RUNNING') : t('FILE_PREVIEW.LAUNCH_BTN')}</button>`\n : `<button class=\"btn-launch\" disabled title=\"${t('FILE_PREVIEW.LAUNCH_LOCAL_ONLY')}\">${t('FILE_PREVIEW.LAUNCH_BTN')}</button>\n <span class=\"launch-hint\">${t('FILE_PREVIEW.LAUNCH_LOCAL_ONLY')}</span>`;\n\n const runResultHtml = runState !== 'idle'\n ? `<div class=\"run-result run-${runState}\">\n <span class=\"run-status\">${t(RUN_STATUS_KEY[runState])}</span>\n ${runOutput ? `<pre class=\"run-output\">${escHtml(runOutput.slice(0, 8000))}</pre>` : ''}\n </div>`\n : '';\n\n return `\n <div class=\"container\">\n <div class=\"header\">\n <span class=\"file-name\">π ${fileName ? escHtml(fileName) : t('FILE_PREVIEW.NO_FILE')}</span>\n <button id=\"btn-copy\" title=\"${t('FILE_PREVIEW.COPY_TITLE')}\">π</button>\n </div>\n <div class=\"body\">\n ${showDiff\n ? `<div class=\"diff-panel\" id=\"diff-panel\">${buildDiffHtml(originalContent ?? '', currentContent, t)}</div>`\n : `<textarea class=\"editor\" id=\"editor\" spellcheck=\"false\">${escHtml(fileContent ?? '')}</textarea>`}\n ${blocksPanelHtml}\n </div>\n ${runResultHtml}\n <div class=\"footer\">\n ${launchBtnHtml}\n ${hasChanges ? `<button id=\"btn-diff\" class=\"${showDiff ? 'btn-diff-active' : ''}\">${t('FILE_PREVIEW.DIFF_BTN')}</button>` : ''}\n ${hasBlocks && !showDiff ? `<button id=\"btn-insert\" class=\"btn-insert\" title=\"${t('FILE_PREVIEW.INSERT_TITLE')}\">${t('FILE_PREVIEW.INSERT_BTN')}</button>` : ''}\n <button id=\"btn-save\" class=\"btn-save\">${t('FILE_PREVIEW.SAVE_BTN')}</button>\n <button id=\"btn-close\">${escHtml(closeLabel || t('FILE_PREVIEW.CLOSE_BTN'))}</button>\n </div>\n </div>`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { advancedTestTransformationService } from '../../services/advanced-test.transformation.service';\r\nimport { showToast } from '../../utils/toast.utils';\r\nimport { isLocalHost } from '../../utils/host.utils';\r\nimport { FILE_PREVIEW_STYLES } from './file-preview.styles';\r\nimport { renderFilePreview, type RunState } from './file-preview.template';\r\n\r\nexport class FilePreviewElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private textarea: HTMLTextAreaElement | null = null;\r\n\r\n fileName: string | null = null;\r\n closeLabel = '';\r\n translation: TranslationService = translationService;\r\n itBlock = '';\r\n interceptorsBlock = '';\r\n notes = '';\r\n commands: string[] = [];\r\n interceptors: string[] = [];\r\n /** Endpoint of the local Cypress runner. Configurable; defaults to the bundled runner's port. */\r\n runnerUrl = 'http://localhost:8123/run-test';\r\n /** Whether the app is served locally β gates the launch button. Overridable for tests. */\r\n isLocal = isLocalHost(window.location.hostname);\r\n private _fileContent: string | null = null;\r\n private _originalContent: string | null = null;\r\n private _showDiff = false;\r\n private _runState: RunState = 'idle';\r\n private _runOutput = '';\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.closeLabel) this.closeLabel = this.translation.translate('FILE_PREVIEW.CLOSE_BTN');\r\n this.render();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n get fileContent(): string | null { return this._fileContent; }\r\n set fileContent(v: string | null) {\r\n if (this._originalContent === null) this._originalContent = v;\r\n this._fileContent = v;\r\n if (this.textarea) this.textarea.value = v ?? '';\r\n else this.render();\r\n }\r\n\r\n saveFile(): void {\r\n const content = this.textarea?.value ?? this._fileContent ?? '';\r\n this.dispatchEvent(new CustomEvent('save', { detail: content, bubbles: true, composed: true }));\r\n }\r\n\r\n onClose(): void {\r\n this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }));\r\n }\r\n\r\n /**\r\n * Runs the current spec headless via the local runner and shows the result.\r\n * No-op off localhost. Never throws β connection failures surface as an\r\n * \"error\" state + toast instead of an unhandled rejection.\r\n */\r\n async launchTest(specPath?: string): Promise<void> {\r\n if (!this.isLocal) return;\r\n const path = specPath ?? this.fileName ?? '';\r\n if (!path) return;\r\n\r\n this._runState = 'running';\r\n this._runOutput = '';\r\n this.render();\r\n\r\n try {\r\n const response = await fetch(this.runnerUrl, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ specPath: path }),\r\n });\r\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\r\n const result = await response.json() as { success?: boolean; output?: string };\r\n this._runOutput = result.output ?? '';\r\n this._runState = result.success ? 'passed' : 'failed';\r\n } catch {\r\n this._runState = 'error';\r\n this._runOutput = '';\r\n showToast(this.t('FILE_PREVIEW.LAUNCH_NO_RUNNER'), false);\r\n }\r\n this.render();\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n toggleDiff(): void {\r\n this._showDiff = !this._showDiff;\r\n this.render();\r\n }\r\n\r\n /**\r\n * Merges the it() and beforeEach() blocks into the current editor content\r\n * using the same logic as the automatic \"Insert into file\" action, so the\r\n * user does not have to copy/paste manually. Leaves the content untouched\r\n * (and warns) when the file has no valid describe() block to insert into.\r\n */\r\n insertBlocks(): void {\r\n const base = this.textarea?.value ?? this._fileContent ?? '';\r\n let content = base;\r\n if (this.interceptorsBlock) {\r\n const merged = advancedTestTransformationService.insertBeforeEach(content, this.interceptorsBlock);\r\n if (merged) content = merged;\r\n }\r\n if (this.itBlock) {\r\n const comment = this.notes ? advancedTestTransformationService.buildBlockComment(this.notes) + '\\n' : '';\r\n const merged = advancedTestTransformationService.insertItBlock(content, comment + this.itBlock);\r\n if (merged) content = merged;\r\n }\r\n if (content === base) {\r\n showToast(this.t('FILE_PREVIEW.INSERT_ERROR'), false);\r\n return;\r\n }\r\n this._fileContent = content;\r\n this.render();\r\n showToast(this.t('FILE_PREVIEW.INSERT_DONE'));\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${FILE_PREVIEW_STYLES}</style>${renderFilePreview({\r\n fileName: this.fileName,\r\n showDiff: this._showDiff,\r\n fileContent: this._fileContent,\r\n originalContent: this._originalContent,\r\n currentContent: this.textarea?.value ?? this._fileContent ?? '',\r\n itBlock: this.itBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n closeLabel: this.closeLabel,\r\n isLocal: this.isLocal,\r\n runState: this._runState,\r\n runOutput: this._runOutput,\r\n }, this.t.bind(this))}`;\r\n\r\n this.textarea = this.shadow.getElementById('editor') as HTMLTextAreaElement | null;\r\n if (this.textarea) {\r\n const ta = this.textarea;\r\n this.textarea.addEventListener('input', () => {\r\n this._fileContent = ta.value;\r\n });\r\n }\r\n this.shadow.getElementById('btn-save')?.addEventListener('click', () => this.saveFile());\r\n this.shadow.getElementById('btn-close')?.addEventListener('click', () => this.onClose());\r\n this.shadow.getElementById('btn-launch')?.addEventListener('click', () => this.launchTest());\r\n this.shadow.getElementById('btn-copy')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.textarea?.value ?? this._fileContent ?? '');\r\n });\r\n this.shadow.getElementById('btn-diff')?.addEventListener('click', () => this.toggleDiff());\r\n this.shadow.getElementById('btn-insert')?.addEventListener('click', () => this.insertBlocks());\r\n this.shadow.getElementById('btn-copy-it')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.itBlock);\r\n });\r\n this.shadow.getElementById('btn-copy-icp')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.interceptorsBlock);\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('file-preview')) {\r\n customElements.define('file-preview', FilePreviewElement);\r\n}\r\n","import Swal from 'sweetalert2';\r\nimport { getRecorderStyles } from './lib-e2e-recorder.styles';\r\nimport { renderRecorderWidget } from './lib-e2e-recorder.template';\r\nimport { RecordingService, type SelectorStrategy } from '../../services/recording.service';\r\nimport { PersistenceService } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport { HttpMonitor } from '../../services/http-monitor';\r\nimport {\r\n injectStyles,\r\n LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES,\r\n SCROLLBAR_STYLES,\r\n} from '../../utils/styles.utils';\r\nimport {\r\n makeModalResizable,\r\n makeSwalDraggable,\r\n setSwal2DataCyAttribute,\r\n} from '../../utils/modal.utils';\r\nimport type { Lang } from '../../models/lang.model';\r\nimport {\r\n type ActiveSessionState,\r\n ACTIVE_SESSION_BREADCRUMB_KEY,\r\n RESUME_TTL_CONFIG_KEY,\r\n DEFAULT_RESUME_TTL_MINUTES,\r\n} from '../../models/active-session.model';\r\nimport { showToast } from '../../utils/toast.utils';\r\n\r\n/**\r\n * Minimal property/event shapes for dynamically-created child custom elements.\r\n * Not extending HTMLElement avoids conflicts with the strict EventListener signature;\r\n * cast to Node/HTMLElement only for actual DOM insertion.\r\n */\r\ninterface PrevisualizerEl {\r\n translation: TranslationService; commands: string[]; interceptors: string[]; editable: boolean;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface TestEditorEl { persistence: PersistenceService; translation: TranslationService }\r\ninterface SaveTestEl {\r\n translation: TranslationService;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface ConfigEl {\r\n persistence: PersistenceService; translation: TranslationService;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface AdvancedEditorEl {\r\n persistence: PersistenceService; translation: TranslationService; testId?: number;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void | Promise<void>): void;\r\n}\r\ninterface FilePreviewEl {\r\n translation: TranslationService; fileContent: string | null; fileName: string | null;\r\n closeLabel: string; itBlock: string; interceptorsBlock: string; notes: string;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void | Promise<void>): void;\r\n}\r\ninterface SelectorPickerEl {\r\n targetElement: HTMLElement; recording: RecordingService; translation: TranslationService;\r\n}\r\n\r\nexport class LibE2eRecorderElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private _isDisabled = false;\r\n private keydownHandler!: (e: KeyboardEvent) => void;\r\n private recordingUnsub?: () => void;\r\n private commandsUnsub?: () => void;\r\n private interceptorsUnsub?: () => void;\r\n private pauseUnsub?: () => void;\r\n private selectorNotFoundUnsub?: () => void;\r\n private langUnsub?: () => void;\r\n private sessionUnsub?: () => void;\r\n private sessionSaveTimer?: ReturnType<typeof setTimeout>;\r\n private controlFirstTimeData = true;\r\n private _previsualizerRef: { commands: string[]; interceptors: string[] } | null = null;\r\n private httpMonitor?: HttpMonitor;\r\n private smartSelectorEnabled = true;\r\n\r\n recording!: RecordingService;\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n\r\n isVisible = false;\r\n isRecording = false;\r\n isPaused = false;\r\n cypressCommands: string[] = [];\r\n interceptors: string[] = [];\r\n\r\n isCommandsDialogOpen = false;\r\n isSavedTestsDialogOpen = false;\r\n isSaveTestDialogOpen = false;\r\n isSettingsDialogOpen = false;\r\n isAdvancedEditorDialogOpen = false;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if ('Cypress' in window) {\r\n this._isDisabled = true;\r\n return;\r\n }\r\n if (!this.getAttribute('data-cy')) {\r\n this.setAttribute('data-cy', 'lib-e2e-cypress-for-dummys');\r\n }\r\n if (!this.recording) this.recording = new RecordingService();\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n\r\n this.httpMonitor = new HttpMonitor(this.recording);\r\n this.httpMonitor.install();\r\n\r\n injectStyles(LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES, 'lib-e2e-swal2-styles');\r\n injectStyles(SCROLLBAR_STYLES, 'lib-e2e-scrollbar-styles');\r\n\r\n this.initHttpConfig();\r\n this.initLanguage();\r\n this.initFilesystemAccess();\r\n this.initSelectorStrategy();\r\n this.initSubscriptions();\r\n this.render();\r\n this.initVisibility();\r\n this.initSessionContinuity();\r\n\r\n this.keydownHandler = (e: KeyboardEvent) => this.handleKeyboardEvent(e);\r\n window.addEventListener('keydown', this.keydownHandler);\r\n }\r\n\r\n disconnectedCallback(): void {\r\n if (this._isDisabled) return;\r\n window.removeEventListener('keydown', this.keydownHandler);\r\n // Final flush: if a recording is in progress, persist it synchronously-ish\r\n // before tearing the service down, so an unmount (single-spa per-sub-project\r\n // placement) does not lose the last commands. The realm survives client-side\r\n // navigation, so this async write completes even after the element is gone.\r\n this.flushActiveSessionOnDisconnect();\r\n this.recordingUnsub?.();\r\n this.commandsUnsub?.();\r\n this.interceptorsUnsub?.();\r\n this.pauseUnsub?.();\r\n this.selectorNotFoundUnsub?.();\r\n this.langUnsub?.();\r\n this.sessionUnsub?.();\r\n this.httpMonitor?.uninstall();\r\n this.recording.destroy();\r\n }\r\n\r\n private async initHttpConfig(): Promise<void> {\r\n const config = await this.persistence.getConfig('extendedHttpCommands');\r\n if (config === null) {\r\n await this.persistence.setConfig({ extendedHttpCommands: 'true' });\r\n localStorage.setItem('extendedHttpCommands', 'true');\r\n } else {\r\n localStorage.setItem('extendedHttpCommands', (config['extendedHttpCommands'] as string) ?? 'true');\r\n }\r\n }\r\n\r\n private async initLanguage(): Promise<void> {\r\n const config = await this.persistence.getConfig('language');\r\n const lang = config?.['language'] as Lang | undefined;\r\n this.translation.setLang(lang ?? this.translation.detectLang());\r\n }\r\n\r\n private initSubscriptions(): void {\r\n this.recordingUnsub = this.recording.onRecordingChange((val) => {\r\n this.isRecording = val;\r\n if (!val && !this.controlFirstTimeData) {\r\n this.saveRecordingHistory();\r\n // Stopping the recording ends the cross-app session: only an actively\r\n // recording session is ever persisted/resumed (spec 006, Q2).\r\n this.clearSessionPersistence();\r\n this.showSaveTestDialog();\r\n }\r\n this.controlFirstTimeData = false;\r\n this.render();\r\n });\r\n // Persist the live session incrementally so it survives a micro-frontend\r\n // crossing or a same-origin reload (spec 006).\r\n this.sessionUnsub = this.recording.onSessionChange((state) => this.persistActiveSession(state));\r\n this.commandsUnsub = this.recording.onCommandsChange((cmds) => {\r\n this.cypressCommands = cmds;\r\n if (this._previsualizerRef) this._previsualizerRef.commands = cmds;\r\n });\r\n this.interceptorsUnsub = this.recording.onInterceptorsChange((icps) => {\r\n this.interceptors = icps;\r\n if (this._previsualizerRef) this._previsualizerRef.interceptors = icps;\r\n });\r\n this.pauseUnsub = this.recording.onPauseChange((paused) => {\r\n this.isPaused = paused;\r\n this.render();\r\n });\r\n this.selectorNotFoundUnsub = this.recording.onSelectorNotFound((target) => {\r\n if (this.smartSelectorEnabled) this.showSelectorPicker(target);\r\n });\r\n // Re-render the widget chrome when the UI language changes so labels update live.\r\n this.langUnsub = this.translation.onLangChange(() => this.render());\r\n }\r\n\r\n private showSelectorPicker(target: HTMLElement): void {\r\n import('../../components/selector-picker/selector-picker').then(() => {\r\n const existing = document.querySelector('selector-picker');\r\n if (existing) existing.remove();\r\n\r\n const picker = document.createElement('selector-picker') as unknown as SelectorPickerEl;\r\n picker.targetElement = target;\r\n picker.recording = this.recording;\r\n picker.translation = this.translation;\r\n document.body.appendChild(picker as unknown as Node);\r\n });\r\n }\r\n\r\n private async initVisibility(): Promise<void> {\r\n if (this.hasAttribute('start-hidden')) {\r\n // Attribute overrides DB: presence β hidden, explicit \"false\" β visible\r\n this.isVisible = this.getAttribute('start-hidden') === 'false';\r\n this.style.display = this.isVisible ? '' : 'none';\r\n return;\r\n }\r\n const config = await this.persistence.getGeneralConfig();\r\n this.isVisible = config?.['startHidden'] !== 'true';\r\n this.style.display = this.isVisible ? '' : 'none';\r\n }\r\n\r\n private async initSelectorStrategy(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n const strategy = config?.['selectorStrategy'] as string | undefined;\r\n if (strategy) this.recording.selectorStrategy = strategy as SelectorStrategy;\r\n this.smartSelectorEnabled = config?.['smartSelectorEnabled'] !== 'false';\r\n }\r\n\r\n // ββ cross-app session continuity (spec 006) βββββββββββββββββββββββββββββββ\r\n\r\n /**\r\n * On mount, detect a persisted live recording session and either resume it\r\n * silently (recent) or prompt continue/discard (stale). No-op when there is\r\n * no actively-recording session.\r\n */\r\n private async initSessionContinuity(): Promise<void> {\r\n if (this._isDisabled) return;\r\n const session = await this.persistence.getActiveSession();\r\n if (!session || !session.isRecording) return;\r\n const ttlMin = await this.getResumeTtlMinutes();\r\n const ageMs = Date.now() - session.updatedAt;\r\n if (ageMs <= ttlMin * 60_000) {\r\n this.resumeSessionState(session);\r\n } else {\r\n this.promptResumeOrDiscard(session);\r\n }\r\n }\r\n\r\n private async getResumeTtlMinutes(): Promise<number> {\r\n const config = await this.persistence.getConfig(RESUME_TTL_CONFIG_KEY);\r\n const raw = config?.[RESUME_TTL_CONFIG_KEY];\r\n const n = typeof raw === 'number' ? raw : Number(raw);\r\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_RESUME_TTL_MINUTES;\r\n }\r\n\r\n /** Rehydrates the recorder from a persisted session (no bootstrap re-emitted). */\r\n private resumeSessionState(session: ActiveSessionState): void {\r\n this.recording.restoreSession(session);\r\n this.cypressCommands = session.commands;\r\n this.interceptors = session.interceptors;\r\n this.controlFirstTimeData = false;\r\n this.render();\r\n }\r\n\r\n private async promptResumeOrDiscard(session: ActiveSessionState): Promise<void> {\r\n const t = this.translation.translate.bind(this.translation);\r\n const result = await Swal.fire({\r\n title: t('RECORDER.SESSION_RESUME_TITLE'),\r\n html:\r\n `<div style=\"padding:8px 4px;color:#8b949e;font-size:13px;line-height:1.6\">` +\r\n `<p>${t('RECORDER.SESSION_RESUME_TEXT')}</p>` +\r\n `<p style=\"margin-top:6px;color:#c9d1d9\"><b>${session.commands.length}</b> ${t('RECORDER.SESSION_RESUME_COUNT')}</p>` +\r\n `</div>`,\r\n showCancelButton: true,\r\n confirmButtonText: t('RECORDER.SESSION_CONTINUE_BTN'),\r\n cancelButtonText: t('RECORDER.SESSION_DISCARD_BTN'),\r\n color: '#e6edf3',\r\n });\r\n if (result && (result as { isConfirmed?: boolean }).isConfirmed) {\r\n this.resumeSessionState(session);\r\n } else {\r\n this.discardSession();\r\n }\r\n }\r\n\r\n /** Debounced persistence of the live session; clears it the moment recording stops. */\r\n private persistActiveSession(state: ActiveSessionState): void {\r\n if (this._isDisabled) return;\r\n if (!state.isRecording) {\r\n this.clearSessionPersistence();\r\n return;\r\n }\r\n this.writeSessionBreadcrumb(state);\r\n if (this.sessionSaveTimer) clearTimeout(this.sessionSaveTimer);\r\n this.sessionSaveTimer = setTimeout(() => {\r\n const snap = this.recording.getSessionSnapshot();\r\n if (snap.isRecording) this.persistence.saveActiveSession(snap).catch(() => { /* storage errors are non-fatal */ });\r\n }, 300);\r\n }\r\n\r\n private writeSessionBreadcrumb(state: ActiveSessionState): void {\r\n try {\r\n localStorage.setItem(ACTIVE_SESSION_BREADCRUMB_KEY, JSON.stringify({\r\n sessionId: state.sessionId,\r\n isRecording: state.isRecording,\r\n updatedAt: state.updatedAt,\r\n }));\r\n } catch { /* ignore storage errors */ }\r\n }\r\n\r\n private flushActiveSessionOnDisconnect(): void {\r\n const snap = this.recording.getSessionSnapshot();\r\n if (!snap.isRecording) return;\r\n if (this.sessionSaveTimer) clearTimeout(this.sessionSaveTimer);\r\n this.writeSessionBreadcrumb(snap);\r\n this.persistence.saveActiveSession(snap).catch(() => { /* non-fatal */ });\r\n }\r\n\r\n private clearSessionPersistence(): void {\r\n if (this.sessionSaveTimer) { clearTimeout(this.sessionSaveTimer); this.sessionSaveTimer = undefined; }\r\n try { localStorage.removeItem(ACTIVE_SESSION_BREADCRUMB_KEY); } catch { /* ignore */ }\r\n this.persistence.clearActiveSession().catch(() => { /* non-fatal */ });\r\n }\r\n\r\n /** True when a synchronous breadcrumb marks an active recording session. */\r\n hasActiveSession(): boolean {\r\n try {\r\n const raw = localStorage.getItem(ACTIVE_SESSION_BREADCRUMB_KEY);\r\n if (!raw) return false;\r\n return !!(JSON.parse(raw) as { isRecording?: boolean }).isRecording;\r\n } catch { return false; }\r\n }\r\n\r\n /** Programmatically resume the persisted session, if any. */\r\n resumeSession(): void {\r\n this.persistence.getActiveSession().then((s) => { if (s) this.resumeSessionState(s); });\r\n }\r\n\r\n /** Discard the persisted live session (breadcrumb + DB record). */\r\n discardSession(): void {\r\n this.clearSessionPersistence();\r\n }\r\n\r\n toggle(): void {\r\n this.recording.toggleRecording();\r\n }\r\n\r\n togglePause(): void {\r\n this.recording.togglePause();\r\n }\r\n\r\n setLanguage(lang?: string): void {\r\n const resolved = lang ? (lang as Lang) : this.translation.detectLang();\r\n this.translation.setLang(resolved);\r\n }\r\n\r\n handleKeyboardEvent(event: KeyboardEvent): void {\r\n if (!event.ctrlKey) return;\r\n const key = event.key.toLowerCase();\r\n if (key === 'e' && event.shiftKey) { event.preventDefault(); this.toggleVisibility(); return; }\r\n if (!this.isVisible) return;\r\n if (key === 'r') { event.preventDefault(); this.toggle(); }\r\n else if (key === 'p') { event.preventDefault(); this.togglePause(); }\r\n else if (key === '1') { event.preventDefault(); this.showSavedTestsDialog(); }\r\n else if (key === '2') { event.preventDefault(); this.showCommandsDialog(); }\r\n else if (key === '3') { event.preventDefault(); this.showSettingsDialog(); }\r\n }\r\n\r\n toggleVisibility(): void {\r\n this.isVisible = !this.isVisible;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n }\r\n\r\n // ββ recording history (task 5) ββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private saveRecordingHistory(): void {\r\n if (!this.cypressCommands.length) return;\r\n try {\r\n const existing = JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n existing.unshift({ commands: this.cypressCommands, interceptors: this.interceptors, savedAt: Date.now() });\r\n if (existing.length > 5) existing.splice(5);\r\n localStorage.setItem('e2e-recording-history', JSON.stringify(existing));\r\n } catch { /* ignore storage errors */ }\r\n }\r\n\r\n recoverLastRecording(): void {\r\n try {\r\n const existing = JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n if (!existing.length) return;\r\n const { commands, interceptors } = existing[0];\r\n commands.forEach((cmd: string) => this.recording.appendCommand(cmd));\r\n (interceptors as string[]).forEach((_icp: string) => { /* interceptors are not appendable the same way */ });\r\n } catch { /* ignore */ }\r\n }\r\n\r\n clearRecordingHistory(): void {\r\n localStorage.removeItem('e2e-recording-history');\r\n }\r\n\r\n getRecordingHistory(): Array<{ commands: string[]; interceptors: string[]; savedAt: number }> {\r\n try {\r\n return JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n } catch { return []; }\r\n }\r\n\r\n // ββ filesystem setup βββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private async initFilesystemAccess(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n // Only show if the user has never made a choice (key doesn't exist yet)\r\n if (config && 'allowReadWriteFiles' in config) return;\r\n this.showFilesystemSetupDialog();\r\n }\r\n\r\n private showFilesystemSetupDialog(): void {\r\n Swal.fire({\r\n title: this.translation.translate('RECORDER.FS_TITLE'),\r\n html: '<div id=\"fs-setup-content\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('fs-setup-content');\r\n if (!container) return;\r\n container.innerHTML = `\r\n <div style=\"padding:16px 20px 20px;color:#8b949e;font-size:13px;line-height:1.7\">\r\n <p>${this.translation.translate('RECORDER.FS_INTRO_HTML')}</p>\r\n <p style=\"margin-top:10px;margin-bottom:6px;font-size:11px;color:#8b949e\">\r\n ${this.translation.translate('RECORDER.FS_STRUCTURE_HINT_HTML')}\r\n </p>\r\n <pre style=\"margin:0;padding:10px 14px;background:#0d1117;border:1px solid #21262d;\r\n border-radius:8px;font-size:11px;color:#c9d1d9;line-height:1.8;\r\n font-family:'Cascadia Code','Fira Code','Consolas',monospace\">\r\ncypress/ <span style=\"color:#484f58\">${this.translation.translate('RECORDER.FS_TREE_PICK_HINT')}</span>\r\nβββ e2e/ <span style=\"color:#484f58\">${this.translation.translate('RECORDER.FS_TREE_READ_HINT')}</span>\r\n βββ *.cy.ts</pre>\r\n <p style=\"margin-top:8px;font-size:11px;color:#484f58\">\r\n ${this.translation.translate('RECORDER.FS_PERMISSION_NOTE')}\r\n </p>\r\n <div style=\"display:flex;gap:8px;justify-content:flex-end;margin-top:20px\">\r\n <button id=\"fs-skip\"\r\n style=\"padding:7px 16px;border:1px solid #30363d;border-radius:6px;cursor:pointer;\r\n font-size:12px;font-weight:500;background:transparent;color:#8b949e\">\r\n ${this.translation.translate('RECORDER.FS_LATER_BTN')}\r\n </button>\r\n <button id=\"fs-select\"\r\n style=\"padding:7px 16px;border:none;border-radius:6px;cursor:pointer;\r\n font-size:12px;font-weight:500;background:#2f81f7;color:#fff\">\r\n ${this.translation.translate('RECORDER.FS_SELECT_BTN')}\r\n </button>\r\n </div>\r\n </div>`;\r\n\r\n document.getElementById('fs-skip')?.addEventListener('click', async () => {\r\n await this.persistence.setConfigKey('allowReadWriteFiles', 'false');\r\n Swal.close();\r\n });\r\n\r\n document.getElementById('fs-select')?.addEventListener('click', async () => {\r\n try {\r\n await this.persistence.requestDirectoryPermissions();\r\n Swal.close();\r\n showToast(this.translation.translate('RECORDER.FS_SUCCESS_TOAST'));\r\n } catch (e: unknown) {\r\n if ((e as DOMException)?.name !== 'AbortError') {\r\n showToast(this.translation.translate('RECORDER.FS_ERROR_TOAST'), false);\r\n }\r\n // AbortError = user cancelled the picker, leave dialog open\r\n }\r\n });\r\n },\r\n });\r\n }\r\n\r\n // ββ dialogs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n showCommandsDialog(): void {\r\n this.toggleModal('isCommandsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_COMMANDS'),\r\n html: '<div id=\"commands-modal-content\" style=\"min-height:250px;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n backdrop: false,\r\n width: 640,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n // Make the container click-through so the page underneath remains interactive\r\n const swalContainer = document.querySelector('.swal2-container') as HTMLElement | null;\r\n if (swalContainer) {\r\n swalContainer.style.pointerEvents = 'none';\r\n const popup = swalContainer.querySelector('.swal2-popup') as HTMLElement | null;\r\n if (popup) popup.style.pointerEvents = 'all';\r\n }\r\n const container = document.getElementById('commands-modal-content');\r\n if (!container) return;\r\n\r\n const child = document.createElement('test-previsualizer') as unknown as PrevisualizerEl;\r\n child.translation = this.translation;\r\n child.commands = this.cypressCommands;\r\n child.interceptors = this.interceptors;\r\n child.editable = true;\r\n container.appendChild(child as unknown as Node);\r\n this._previsualizerRef = child;\r\n\r\n child.addEventListener('deletecommand', (e: CustomEvent) => {\r\n this.recording.removeCommand(e.detail);\r\n });\r\n child.addEventListener('movecommand', (e: CustomEvent) => {\r\n this.recording.moveCommand(e.detail.from, e.detail.to);\r\n });\r\n child.addEventListener('deleteinterceptor', (e: CustomEvent) => {\r\n this.recording.removeInterceptor(e.detail);\r\n });\r\n\r\n // ββ Assertion builder panel ββββββββββββββββββββββββββββββββββββββ\r\n const assertionHtml = `\r\n <div id=\"assertion-builder\"\r\n style=\"padding:10px 12px;border-top:1px solid #21262d;background:#0d1117\">\r\n <div style=\"font-size:10px;color:#484f58;text-transform:uppercase;letter-spacing:.8px;font-weight:600;margin-bottom:8px\">\r\n ${this.translation.translate('RECORDER.ASSERTION_SECTION')}\r\n </div>\r\n <div style=\"display:flex;gap:6px;flex-wrap:wrap;align-items:flex-end\">\r\n <input id=\"assert-selector\" type=\"text\"\r\n placeholder=\"${this.translation.translate('RECORDER.ASSERT_SELECTOR_PH').replace(/\"/g, '"')}\"\r\n style=\"flex:2;min-width:140px;padding:5px 8px;background:#161b22;border:1px solid #30363d;\r\n border-radius:5px;color:#c9d1d9;font-size:11px;outline:none;\r\n font-family:'Cascadia Code','Fira Code',monospace\"/>\r\n <select id=\"assert-type\"\r\n style=\"padding:5px 8px;background:#161b22;border:1px solid #30363d;border-radius:5px;\r\n color:#c9d1d9;font-size:11px;outline:none;cursor:pointer;flex-shrink:0\">\r\n <option value=\"be.visible\">be.visible</option>\r\n <option value=\"not.exist\">not.exist</option>\r\n <option value=\"be.disabled\">be.disabled</option>\r\n <option value=\"be.checked\">be.checked</option>\r\n <option value=\"contain.text\">contain.text</option>\r\n <option value=\"have.value\">have.value</option>\r\n <option value=\"have.length\">have.length</option>\r\n <option value=\"have.class\">have.class</option>\r\n <option value=\"have.attr\">have.attr</option>\r\n </select>\r\n <input id=\"assert-value\" type=\"text\" placeholder=\"${this.translation.translate('RECORDER.ASSERT_VALUE_PH')}\"\r\n style=\"flex:2;min-width:110px;padding:5px 8px;background:#161b22;border:1px solid #30363d;\r\n border-radius:5px;color:#c9d1d9;font-size:11px;outline:none\"/>\r\n <button id=\"btn-add-assertion\"\r\n style=\"padding:5px 12px;border:none;border-radius:5px;cursor:pointer;\r\n font-size:11px;font-weight:500;background:#2f81f7;color:#fff;\r\n white-space:nowrap;flex-shrink:0\">\r\n ${this.translation.translate('RECORDER.ASSERT_ADD_BTN')}\r\n </button>\r\n </div>\r\n </div>`;\r\n container.insertAdjacentHTML('beforeend', assertionHtml);\r\n\r\n const NO_VALUE_ASSERTIONS = new Set(['be.visible', 'not.exist', 'be.disabled', 'be.checked']);\r\n document.getElementById('btn-add-assertion')?.addEventListener('click', () => {\r\n const sel = (document.getElementById('assert-selector') as HTMLInputElement).value.trim();\r\n const type = (document.getElementById('assert-type') as HTMLSelectElement).value;\r\n const val = (document.getElementById('assert-value') as HTMLInputElement).value.trim();\r\n if (!sel) return;\r\n const cmd = NO_VALUE_ASSERTIONS.has(type) || !val\r\n ? `cy.get('${sel}').should('${type}')`\r\n : `cy.get('${sel}').should('${type}', '${val}')`;\r\n this.recording.appendCommand(cmd);\r\n (document.getElementById('assert-selector') as HTMLInputElement).value = '';\r\n (document.getElementById('assert-value') as HTMLInputElement).value = '';\r\n });\r\n },\r\n willClose: () => {\r\n this.isCommandsDialogOpen = false;\r\n this._previsualizerRef = null;\r\n },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showSavedTestsDialog(): void {\r\n this.toggleModal('isSavedTestsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_SAVED_TESTS'),\r\n html: '<div id=\"saved-tests-modal-content\" style=\"min-height:250px;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n width: 680,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('saved-tests-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('test-editor') as unknown as TestEditorEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n },\r\n willClose: () => { this.isSavedTestsDialogOpen = false; },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showSaveTestDialog(): void {\r\n this.toggleModal('isSaveTestDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_SAVE'),\r\n html: '<div id=\"save-test-modal-content\" style=\"padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('save-test-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('save-test') as unknown as SaveTestEl;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('savetest', (e: CustomEvent) => {\r\n const { description, notes, tags } = e.detail ?? {};\r\n this.onSaveTest(description ?? null, tags ?? [], notes ?? '');\r\n Swal.close();\r\n });\r\n child.addEventListener('saveandexport', (e: CustomEvent) => {\r\n const { description, notes, tags } = e.detail ?? {};\r\n this.onSaveAndExportTest(description ?? null, tags ?? [], notes ?? '');\r\n Swal.close();\r\n });\r\n },\r\n willClose: () => { this.isSaveTestDialogOpen = false; },\r\n });\r\n });\r\n }\r\n\r\n showSettingsDialog(): void {\r\n this.toggleModal('isSettingsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.SETTINGS'),\r\n html: '<div id=\"settings-modal-content\" style=\"padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n width: 520,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('settings-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('e2e-configuration') as unknown as ConfigEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('smartselectorchange', (e: CustomEvent) => {\r\n this.smartSelectorEnabled = e.detail;\r\n });\r\n child.addEventListener('starthiddenchange', (e: CustomEvent) => {\r\n this.isVisible = !e.detail;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n });\r\n },\r\n willClose: () => { this.isSettingsDialogOpen = false; },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showAdvancedEditorDialog(testId?: number): void {\r\n this.toggleModal('isAdvancedEditorDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.SHOW_ADVANCED_EDITOR'),\r\n html: '<div id=\"advanced-editor-modal-content\" style=\"flex:1;min-height:0;display:flex;flex-direction:column;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n width: 780,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const popup = Swal.getPopup();\r\n if (popup) {\r\n popup.style.height = '600px';\r\n const htmlContainer = popup.querySelector('.swal2-html-container') as HTMLElement | null;\r\n if (htmlContainer) {\r\n htmlContainer.style.flex = '1';\r\n htmlContainer.style.minHeight = '0';\r\n htmlContainer.style.overflow = 'hidden';\r\n htmlContainer.style.padding = '0';\r\n htmlContainer.style.margin = '0';\r\n htmlContainer.style.display = 'flex';\r\n htmlContainer.style.flexDirection = 'column';\r\n }\r\n }\r\n const container = document.getElementById('advanced-editor-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('advanced-test-editor') as unknown as AdvancedEditorEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n if (testId !== undefined) child.testId = testId;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('selectorstrategychange', (e: CustomEvent) => {\r\n this.recording.selectorStrategy = e.detail;\r\n });\r\n child.addEventListener('closemodal', () => Swal.close());\r\n child.addEventListener('openfileeditor', (e: CustomEvent) => {\r\n Swal.close();\r\n setTimeout(() => this.showFileEditorDialog(\r\n e.detail.handle, e.detail.content, e.detail.fileName, e.detail.testId,\r\n e.detail.itBlock, e.detail.interceptorsBlock, e.detail.notes,\r\n ), 150);\r\n });\r\n },\r\n willClose: () => { this.isAdvancedEditorDialogOpen = false; },\r\n });\r\n setTimeout(() => {\r\n const popup = Swal.getPopup();\r\n if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 0 });\r\n }, 0);\r\n });\r\n }\r\n\r\n private showFileEditorDialog(\r\n handle: FileSystemFileHandle,\r\n content: string,\r\n fileName: string,\r\n testId?: number,\r\n itBlock = '',\r\n interceptorsBlock = '',\r\n notes = '',\r\n ): void {\r\n Swal.fire({\r\n title: this.translation.translate('RECORDER.FILE_EDITOR_TITLE'),\r\n html: '<div id=\"file-editor-modal-content\" style=\"padding:0;height:540px\"></div>',\r\n showCloseButton: false,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n width: 1100,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('file-editor-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('file-preview') as unknown as FilePreviewEl;\r\n child.translation = this.translation;\r\n child.fileContent = content;\r\n child.fileName = fileName;\r\n child.closeLabel = this.translation.translate('FILE_PREVIEW.BACK_TO_EDITOR');\r\n child.itBlock = itBlock;\r\n child.interceptorsBlock = interceptorsBlock;\r\n child.notes = notes;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('close', () => {\r\n Swal.close();\r\n setTimeout(() => this.showAdvancedEditorDialog(testId), 150);\r\n });\r\n child.addEventListener('save', async (e: CustomEvent) => {\r\n try {\r\n const writable = await handle.createWritable();\r\n await writable.write(e.detail);\r\n await writable.close();\r\n showToast(this.translation.translate('RECORDER.FILE_SAVED_TOAST'));\r\n } catch {\r\n showToast(this.translation.translate('RECORDER.FILE_SAVE_ERROR_TOAST'), false);\r\n }\r\n Swal.close();\r\n setTimeout(() => this.showAdvancedEditorDialog(testId), 150);\r\n });\r\n },\r\n });\r\n this.resizePopup();\r\n }\r\n\r\n // ββ save handlers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private async onSaveTest(description: string | null, tags: string[] = [], notes = ''): Promise<void> {\r\n if (description) {\r\n await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);\r\n this.recording.clearCommands();\r\n this.clearRecordingHistory();\r\n this.cypressCommands = [];\r\n this.interceptors = [];\r\n }\r\n }\r\n\r\n private async onSaveAndExportTest(description: string | null, tags: string[] = [], notes = ''): Promise<void> {\r\n if (description) {\r\n const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);\r\n this.recording.clearCommands();\r\n this.clearRecordingHistory();\r\n this.cypressCommands = [];\r\n this.interceptors = [];\r\n setTimeout(() => this.showAdvancedEditorDialog(id), 300);\r\n }\r\n }\r\n\r\n // ββ helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private toggleModal(flag: keyof this, openFn: () => void): void {\r\n if (this[flag]) {\r\n Swal.close();\r\n (this as Record<string, unknown>)[flag as string] = false;\r\n return;\r\n }\r\n (this as Record<string, unknown>)[flag as string] = true;\r\n openFn();\r\n }\r\n\r\n private resizePopup(): void {\r\n setTimeout(() => {\r\n const popup = Swal.getPopup();\r\n if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 200 });\r\n }, 0);\r\n }\r\n\r\n private render(): void {\r\n const rec = this.isRecording;\r\n const paused = this.isPaused;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n this.shadow.innerHTML = `<style>${getRecorderStyles(rec, paused)}</style>${renderRecorderWidget(rec, paused, this.translation.translate.bind(this.translation))}`;\r\n this.shadow.querySelector('[data-action=\"toggle\"]')\r\n ?.addEventListener('click', () => this.toggle());\r\n this.shadow.querySelector('[data-action=\"pause\"]')\r\n ?.addEventListener('click', () => this.togglePause());\r\n this.shadow.querySelector('[data-action=\"tests\"]')\r\n ?.addEventListener('click', () => this.showSavedTestsDialog());\r\n this.shadow.querySelector('[data-action=\"commands\"]')\r\n ?.addEventListener('click', () => this.showCommandsDialog());\r\n this.shadow.querySelector('[data-action=\"config\"]')\r\n ?.addEventListener('click', () => this.showSettingsDialog());\r\n this.shadow.querySelector('[data-action=\"browse\"]')\r\n ?.addEventListener('click', () => this.showAdvancedEditorDialog());\r\n }\r\n}\r\n\r\nif (!customElements.get('lib-e2e-recorder')) {\r\n customElements.define('lib-e2e-recorder', LibE2eRecorderElement);\r\n}\r\n","export function getRecorderStyles(rec: boolean, paused: boolean): string {\n return `\n :host { all: initial; }\n *, *::before, *::after { box-sizing: border-box; }\n\n /*\n * Invisible 190Γ190 hit area anchored at bottom-right.\n * Keeps :hover alive while the cursor travels from the\n * toggle to any of the radial action buttons.\n */\n .widget {\n position: fixed;\n bottom: 0;\n right: 0;\n width: 190px;\n height: 190px;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n }\n\n /* ββ Toggle ββββββββββββββββββββββββββββββββββββββββ */\n .btn-toggle {\n position: absolute;\n bottom: 24px;\n right: 24px;\n width: 44px;\n height: 44px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n font-size: 19px;\n background: ${rec\n ? 'linear-gradient(135deg,#f85149 0%,#da3633 100%)'\n : 'linear-gradient(135deg,#2f81f7 0%,#1f6feb 100%)'};\n color: #fff;\n box-shadow: ${rec\n ? '0 4px 20px rgba(248,81,73,.55),0 0 0 4px rgba(248,81,73,.13)'\n : '0 4px 20px rgba(47,129,247,.45),0 0 0 4px rgba(47,129,247,.11)'};\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform .18s, box-shadow .2s;\n z-index: 2;\n ${rec ? 'animation: toggle-pulse 2s ease-in-out infinite;' : ''}\n }\n .btn-toggle:hover { transform: scale(1.1); }\n .btn-toggle:active { transform: scale(0.93); }\n\n @keyframes toggle-pulse {\n 0%,100% { box-shadow: 0 4px 20px rgba(248,81,73,.55),0 0 0 4px rgba(248,81,73,.13); }\n 50% { box-shadow: 0 6px 28px rgba(248,81,73,.75),0 0 0 8px rgba(248,81,73,.06); }\n }\n\n /* ββ Pause button ββββββββββββββββββββββββββββββββββ */\n .btn-pause {\n position: absolute;\n bottom: 78px;\n right: 24px;\n width: 34px;\n height: 34px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n font-size: 15px;\n display: ${rec ? 'flex' : 'none'};\n align-items: center;\n justify-content: center;\n background: ${paused\n ? 'linear-gradient(135deg,#2f81f7 0%,#1f6feb 100%)'\n : 'rgba(13,17,23,0.85)'};\n color: ${paused ? '#fff' : '#e3b341'};\n box-shadow: 0 2px 12px rgba(0,0,0,.4), 0 0 0 1px rgba(48,54,61,.8);\n transition: transform .15s, background .2s, color .2s;\n z-index: 2;\n }\n .btn-pause:hover { transform: scale(1.12); }\n .btn-pause:active { transform: scale(0.93); }\n\n /* ββ Action buttons ββββββββββββββββββββββββββββββββ */\n /*\n * All three start centered on the toggle button\n * (toggle center = bottom:46px right:46px from widget edge;\n * button half = 18px β bottom:28px right:28px).\n */\n .btn-action {\n position: absolute;\n bottom: 28px;\n right: 28px;\n width: 36px;\n height: 36px;\n border-radius: 50%;\n border: none;\n cursor: pointer;\n font-size: 16px;\n display: flex;\n align-items: center;\n justify-content: center;\n background: rgba(13,17,23,.92);\n backdrop-filter: blur(14px);\n -webkit-backdrop-filter: blur(14px);\n color: #8b949e;\n box-shadow: 0 4px 18px rgba(0,0,0,.45), 0 0 0 1px rgba(48,54,61,.75);\n opacity: 0;\n transform: scale(0.35);\n pointer-events: none;\n /* Collapse: fast, no spring */\n transition: opacity .15s, transform .18s ease-in,\n background .15s, color .12s, box-shadow .15s;\n }\n\n /* Label to the left of each button */\n .btn-action::after {\n content: attr(data-label);\n position: absolute;\n right: calc(100% + 9px);\n top: 50%;\n transform: translateY(-50%);\n background: rgba(13,17,23,.95);\n color: #e6edf3;\n font-size: 11px;\n font-weight: 500;\n padding: 3px 9px;\n border-radius: 6px;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n transition: opacity .15s .05s;\n border: 1px solid rgba(48,54,61,.8);\n box-shadow: 0 2px 8px rgba(0,0,0,.35);\n }\n /* Button 1 (top) β label above instead of left to avoid overlap with btn 2 */\n .btn-action[data-n=\"1\"]::after {\n right: auto;\n left: 50%;\n top: auto;\n bottom: calc(100% + 9px);\n transform: translateX(-50%);\n }\n .btn-action:hover::after { opacity: 1; }\n .btn-action:hover { background: #21262d; color: #e6edf3; }\n .btn-action:active { background: #30363d !important; }\n\n /* Expand: spring + stagger */\n .widget:hover .btn-action {\n opacity: 1;\n pointer-events: all;\n transition: opacity .2s, transform .32s cubic-bezier(.34,1.56,.64,1),\n background .15s, color .12s, box-shadow .15s;\n }\n\n /* Arc positions β 4 buttons, 30Β° spacing, radius 90px */\n .widget:hover .btn-action[data-n=\"1\"] { /* 0Β° β straight up */\n transform: translateY(-90px) scale(1);\n transition-delay: .03s;\n }\n .widget:hover .btn-action[data-n=\"2\"] { /* 30Β° β upper-left */\n transform: translate(-45px,-78px) scale(1);\n transition-delay: .07s;\n }\n .widget:hover .btn-action[data-n=\"3\"] { /* 60Β° β left-upper */\n transform: translate(-78px,-45px) scale(1);\n transition-delay: .11s;\n }\n .widget:hover .btn-action[data-n=\"4\"] { /* 90Β° β straight left */\n transform: translateX(-90px) scale(1);\n transition-delay: .15s;\n }\n /* Button 4 (pure left) β label above to avoid going off-screen */\n .btn-action[data-n=\"4\"]::after {\n right: auto;\n left: 50%;\n top: auto;\n bottom: calc(100% + 9px);\n transform: translateX(-50%);\n }\n\n /* ββ REC / PAUSED badge ββββββββββββββββββββββββββββ */\n .rec-badge {\n position: fixed;\n top: 14px;\n left: 50%;\n transform: translateX(-50%);\n background: ${paused\n ? 'linear-gradient(90deg,#e3b341,#d29922)'\n : 'linear-gradient(90deg,#f85149,#da3633)'};\n color: #fff;\n padding: 3px 16px;\n border-radius: 20px;\n font-size: 10px;\n font-weight: 700;\n letter-spacing: 2px;\n text-transform: uppercase;\n z-index: 2147483647;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: ${paused\n ? '0 4px 16px rgba(227,179,65,.4)'\n : '0 4px 16px rgba(248,81,73,.4)'};\n display: ${rec ? 'block' : 'none'};\n ${!paused ? 'animation: rec-pulse 1.8s ease-in-out infinite;' : ''}\n }\n @keyframes rec-pulse {\n 0%,100% { opacity: 1; }\n 50% { opacity: 0.6; }\n }\n `;\n}\n","export function renderRecorderWidget(rec: boolean, paused: boolean, t: (key: string) => string): string {\n return `\n <div class=\"widget\">\n <button class=\"btn-action\" data-n=\"1\" data-action=\"config\"\n data-label=\"${t('RECORDER.BTN_CONFIG')}\">βοΈ</button>\n <button class=\"btn-action\" data-n=\"2\" data-action=\"browse\"\n data-label=\"${t('RECORDER.BTN_FILES')}\">π</button>\n <button class=\"btn-action\" data-n=\"3\" data-action=\"commands\"\n data-label=\"${t('RECORDER.BTN_COMMANDS')}\">β¨οΈ</button>\n <button class=\"btn-action\" data-n=\"4\" data-action=\"tests\"\n data-label=\"${t('RECORDER.BTN_TESTS')}\">π</button>\n <button class=\"btn-pause\" data-action=\"pause\"\n title=\"${paused ? t('RECORDER.RESUME_TITLE') : t('RECORDER.PAUSE_TITLE')}\">\n ${paused ? 'βΆ' : 'βΈ'}\n </button>\n <button class=\"btn-toggle\" data-action=\"toggle\"\n title=\"${rec ? t('RECORDER.STOP_TITLE') : t('RECORDER.START_TITLE')}\">\n ${rec ? 'βΉ' : 'βΊ'}\n </button>\n </div>\n <div class=\"rec-badge\">${paused ? t('RECORDER.BADGE_PAUSED') : t('RECORDER.BADGE_REC')}</div>`;\n}\n"],"mappings":"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","names":["tag","container","rect","input","folderInput","i","j","Swal"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/selector-quality.utils.ts","../src/components/selector-picker/selector-picker.styles.ts","../src/utils/html.utils.ts","../src/components/selector-picker/selector-picker.template.ts","../src/components/selector-picker/selector-picker.ts","../src/index.ts","../src/models/lang.model.ts","../src/models/input-types.model.ts","../src/models/db-schema.model.ts","../src/models/active-session.model.ts","../src/utils/subject.ts","../src/i18n/es.ts","../src/i18n/en.ts","../src/i18n/fr.ts","../src/i18n/it.ts","../src/i18n/de.ts","../src/services/translation.service.ts","../src/utils/code-format.utils.ts","../src/services/transformation.service.ts","../src/services/advanced-test.transformation.service.ts","../src/services/recording.service.ts","../src/services/persistence.service.ts","../src/services/http-monitor.ts","../src/utils/styles.utils.ts","../src/utils/modal.utils.ts","../src/utils/toast.utils.ts","../src/utils/export-selection.utils.ts","../src/utils/host.utils.ts","../src/utils/widget-position.utils.ts","../src/components/test-previsualizer/test-previsualizer.styles.ts","../src/components/test-previsualizer/test-previsualizer.template.ts","../src/components/test-previsualizer/test-previsualizer.ts","../src/components/save-test/save-test.styles.ts","../src/components/save-test/save-test.template.ts","../src/components/save-test/save-test.ts","../src/components/test-editor/test-editor.styles.ts","../src/components/test-editor/test-editor.template.ts","../src/utils/syntax-highlight.utils.ts","../src/components/test-editor/test-editor.ts","../src/components/configuration/configuration.styles.ts","../src/components/configuration/configuration.template.ts","../src/components/configuration/configuration.ts","../src/components/advanced-test-editor/advanced-test-editor.styles.ts","../src/components/advanced-test-editor/advanced-test-editor.template.ts","../src/components/advanced-test-editor/advanced-test-editor.ts","../src/components/file-preview/file-preview.styles.ts","../src/components/file-preview/file-preview.template.ts","../src/components/file-preview/file-preview.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.styles.ts","../src/components/lib-e2e-recorder/lib-e2e-recorder.template.ts"],"sourcesContent":["export type SelectorQuality = 'excellent' | 'good' | 'acceptable' | 'poor';\n\nexport const FORBIDDEN_ID_PREFIXES = [\n 'cdk-', 'mat-', 'p-', 'ng-', 'mdc-',\n 'primeng-', 'auto-', 'field-', 'input-', 'select-',\n];\n\nexport function getSelectorQuality(el: HTMLElement): SelectorQuality {\n if (\n el.hasAttribute('data-cy') ||\n el.hasAttribute('data-testid') ||\n el.hasAttribute('aria-label')\n ) {\n return 'excellent';\n }\n\n const rawId = el.id;\n if (\n rawId &&\n rawId.length < 25 &&\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\n !/^\\d+$/.test(rawId)\n ) {\n return 'good';\n }\n\n if (typeof el.className === 'string' && el.className.trim().length > 0) {\n return 'acceptable';\n }\n\n return 'poor';\n}\n\n/** Returns the best cy.get() selector string for a given element. */\nexport function buildPickerSelector(el: HTMLElement): string {\n const dataCy = el.getAttribute('data-cy');\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\n\n const dataTestid = el.getAttribute('data-testid');\n if (dataTestid) return `[data-testid=\"${dataTestid}\"]`;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\n\n const rawId = el.id;\n if (\n rawId &&\n rawId.length < 25 &&\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\n !/^\\d+$/.test(rawId)\n ) {\n return `#${rawId}`;\n }\n\n if (typeof el.className === 'string' && el.className.trim().length > 0) {\n const classes = el.className.trim().split(/\\s+/);\n return classes.map((c) => `.${c}`).join('');\n }\n\n return el.tagName.toLowerCase();\n}\n\n/** Human-readable key attribute/selector preview for a picker row (raw, unescaped). */\nexport function keyAttrDisplay(el: HTMLElement): string {\n for (const attr of ['data-cy', 'data-testid', 'aria-label']) {\n const v = el.getAttribute(attr);\n if (v) return `${attr}=\"${v}\"`;\n }\n if (el.id) return `id=\"${el.id}\"`;\n if (el.className && el.className.trim()) {\n return el.className.trim().split(/\\s+/).map((c) => `.${c}`).join('');\n }\n return '';\n}\n\n/** Plain, serializable view-model for one picker row β no DOM held. */\nexport interface PickerRow {\n quality: SelectorQuality;\n selector: string;\n tag: string;\n attr: string;\n}\n\n/** Reads an element once and returns the plain data a picker row needs to render. */\nexport function describePickerRow(el: HTMLElement): PickerRow {\n return {\n quality: getSelectorQuality(el),\n selector: buildPickerSelector(el),\n tag: el.tagName.toLowerCase(),\n attr: keyAttrDisplay(el),\n };\n}\n","export const SELECTOR_PICKER_STYLES = `\r\n :host {\r\n position: fixed;\r\n z-index: 2147483647;\r\n top: 0;\r\n left: 0;\r\n width: 100vw;\r\n height: 100vh;\r\n pointer-events: none;\r\n }\r\n\r\n .overlay {\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n pointer-events: all;\r\n background: #161b22;\r\n border: 1px solid #30363d;\r\n border-radius: 10px;\r\n box-shadow: 0 8px 32px rgba(0,0,0,0.6);\r\n min-width: 420px;\r\n max-width: 600px;\r\n font-family: 'Segoe UI', system-ui, sans-serif;\r\n color: #e6edf3;\r\n font-size: 13px;\r\n }\r\n\r\n .header {\r\n padding: 12px 16px 8px;\r\n border-bottom: 1px solid #21262d;\r\n font-weight: 600;\r\n font-size: 13px;\r\n color: #8b949e;\r\n letter-spacing: 0.04em;\r\n text-transform: uppercase;\r\n }\r\n\r\n .list {\r\n max-height: 320px;\r\n overflow-y: auto;\r\n padding: 6px 0;\r\n }\r\n\r\n .row {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n padding: 7px 14px;\r\n cursor: pointer;\r\n border-radius: 6px;\r\n margin: 1px 6px;\r\n transition: background 0.1s;\r\n }\r\n\r\n .row:hover,\r\n .row.selected {\r\n background: #21262d;\r\n }\r\n\r\n .row.selected {\r\n outline: 2px solid #388bfd;\r\n outline-offset: -2px;\r\n }\r\n\r\n .quality-badge {\r\n width: 18px;\r\n height: 18px;\r\n border-radius: 50%;\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n font-size: 10px;\r\n }\r\n\r\n .badge-excellent { background: #238636; }\r\n .badge-good { background: #1f6feb; }\r\n .badge-acceptable{ background: #9e6a03; }\r\n .badge-poor { background: #da3633; }\r\n\r\n .tag-name {\r\n font-family: monospace;\r\n font-size: 12px;\r\n color: #8b949e;\r\n flex-shrink: 0;\r\n }\r\n\r\n .attr-value {\r\n font-family: monospace;\r\n font-size: 12px;\r\n color: #c9d1d9;\r\n flex: 1;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .selector-preview {\r\n font-family: monospace;\r\n font-size: 11px;\r\n color: #58a6ff;\r\n flex-shrink: 0;\r\n max-width: 180px;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n .poor-warning {\r\n font-size: 10px;\r\n color: #f85149;\r\n margin-left: auto;\r\n }\r\n\r\n .footer {\r\n padding: 8px 14px 10px;\r\n border-top: 1px solid #21262d;\r\n display: flex;\r\n gap: 16px;\r\n font-size: 11px;\r\n color: #484f58;\r\n }\r\n\r\n .hint kbd {\r\n background: #21262d;\r\n border: 1px solid #30363d;\r\n border-radius: 3px;\r\n padding: 1px 5px;\r\n font-size: 10px;\r\n color: #8b949e;\r\n }\r\n`;\r\n","export function escHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');\n}\n\nexport function escAttr(s: string): string {\n return s.replace(/\"/g, '"').replace(/</g, '<');\n}\n","import type { PickerRow, SelectorQuality } from '../../utils/selector-quality.utils';\r\nimport { escHtml } from '../../utils/html.utils';\r\n\r\nconst QUALITY_EMOJI: Record<SelectorQuality, string> = {\r\n excellent: 'π’',\r\n good: 'π΅',\r\n acceptable: 'π‘',\r\n poor: 'π΄',\r\n};\r\n\r\nconst QUALITY_CLASS: Record<SelectorQuality, string> = {\r\n excellent: 'badge-excellent',\r\n good: 'badge-good',\r\n acceptable: 'badge-acceptable',\r\n poor: 'badge-poor',\r\n};\r\n\r\nexport function renderPickerRows(\r\n rows: PickerRow[],\r\n selectedIndex: number,\r\n t: (key: string) => string,\r\n): string {\r\n return rows.map((row, i) => {\r\n const isSelected = i === selectedIndex;\r\n const isPoor = row.quality === 'poor';\r\n\r\n return `\r\n <div class=\"row${isSelected ? ' selected' : ''}\" data-idx=\"${i}\" role=\"option\" aria-selected=\"${isSelected}\">\r\n <span class=\"quality-badge ${QUALITY_CLASS[row.quality]}\" title=\"${escHtml(t(`SELECTOR_PICKER.QUALITY_${row.quality.toUpperCase()}`))}\">\r\n ${QUALITY_EMOJI[row.quality]}\r\n </span>\r\n <span class=\"tag-name\"><${escHtml(row.tag)}></span>\r\n ${row.attr ? `<span class=\"attr-value\">${escHtml(row.attr)}</span>` : '<span class=\"attr-value\"></span>'}\r\n <span class=\"selector-preview\">${escHtml(row.selector)}</span>\r\n ${isPoor ? `<span class=\"poor-warning\" title=\"${escHtml(t('SELECTOR_PICKER.QUALITY_POOR'))}\">β </span>` : ''}\r\n </div>`;\r\n }).join('');\r\n}\r\n\r\nexport function renderPicker(\r\n rows: PickerRow[],\r\n selectedIndex: number,\r\n t: (key: string) => string,\r\n): string {\r\n return `\r\n <div class=\"overlay\" role=\"listbox\">\r\n <div class=\"header\">${escHtml(t('SELECTOR_PICKER.TITLE'))}</div>\r\n <div class=\"list\">\r\n ${renderPickerRows(rows, selectedIndex, t)}\r\n </div>\r\n <div class=\"footer\">\r\n <span class=\"hint\"><kbd>ββ</kbd> ${escHtml(t('SELECTOR_PICKER.PREVIEW_LABEL'))}</span>\r\n <span class=\"hint\"><kbd>Enter</kbd> ${escHtml(t('SELECTOR_PICKER.CONFIRM_HINT'))}</span>\r\n <span class=\"hint\"><kbd>Esc</kbd> ${escHtml(t('SELECTOR_PICKER.CANCEL_HINT'))}</span>\r\n </div>\r\n </div>`;\r\n}\r\n","import type { RecordingService } from '../../services/recording.service';\r\nimport type { TranslationService } from '../../services/translation.service';\r\nimport { describePickerRow, type PickerRow } from '../../utils/selector-quality.utils';\r\nimport { SELECTOR_PICKER_STYLES } from './selector-picker.styles';\r\nimport { renderPicker } from './selector-picker.template';\r\n\r\nconst OWN_DATA_CY = 'lib-e2e-cypress-for-dummys';\r\nconst MAX_ANCESTORS = 10;\r\n\r\nexport class SelectorPickerElement extends HTMLElement {\r\n targetElement: HTMLElement | null = null;\r\n recording!: RecordingService;\r\n translation!: TranslationService;\r\n\r\n private shadow: ShadowRoot;\r\n private ancestors: HTMLElement[] = [];\r\n private rows: PickerRow[] = [];\r\n private selectedIndex = 0;\r\n private keyHandler: ((e: KeyboardEvent) => void) | null = null;\r\n private unsubRecording: (() => void) | null = null;\r\n private unsubPause: (() => void) | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n this.setAttribute('data-cy', 'lib-e2e-cypress-for-dummys');\r\n this.ancestors = this.buildAncestors();\r\n this.rows = this.ancestors.map(describePickerRow);\r\n this.selectedIndex = this.findBestIndex();\r\n this.render();\r\n this.attachKeyListener();\r\n this.attachRowClickListeners();\r\n this.subscribeToRecordingChanges();\r\n }\r\n\r\n disconnectedCallback(): void {\r\n this.detachKeyListener();\r\n this.unsubRecording?.();\r\n this.unsubPause?.();\r\n }\r\n\r\n private t(key: string): string {\r\n return this.translation?.translate(key) ?? key;\r\n }\r\n\r\n // ββ Ancestor chain ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private buildAncestors(): HTMLElement[] {\r\n const chain: HTMLElement[] = [];\r\n let current: HTMLElement | null = this.targetElement;\r\n\r\n while (current && current.tagName.toLowerCase() !== 'html' && chain.length < MAX_ANCESTORS) {\r\n if (current.getAttribute('data-cy') === OWN_DATA_CY) {\r\n current = current.parentElement;\r\n continue;\r\n }\r\n chain.push(current);\r\n current = current.parentElement;\r\n }\r\n\r\n return chain;\r\n }\r\n\r\n private findBestIndex(): number {\r\n for (let i = 0; i < this.rows.length; i++) {\r\n const q = this.rows[i].quality;\r\n if (q === 'excellent' || q === 'good' || q === 'acceptable') return i;\r\n }\r\n return 0;\r\n }\r\n\r\n // ββ Rendering βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${SELECTOR_PICKER_STYLES}</style>${renderPicker(\r\n this.rows,\r\n this.selectedIndex,\r\n this.t.bind(this),\r\n )}`;\r\n }\r\n\r\n // ββ Keyboard ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private attachKeyListener(): void {\r\n this.keyHandler = (e: KeyboardEvent) => {\r\n if (e.key === 'ArrowDown') {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.selectedIndex = (this.selectedIndex + 1) % this.ancestors.length;\r\n this.render();\r\n this.attachRowClickListeners();\r\n } else if (e.key === 'ArrowUp') {\r\n e.stopPropagation();\r\n e.preventDefault();\r\n this.selectedIndex = (this.selectedIndex - 1 + this.ancestors.length) % this.ancestors.length;\r\n this.render();\r\n this.attachRowClickListeners();\r\n } else if (e.key === 'Enter') {\r\n e.stopPropagation();\r\n this.confirm(this.selectedIndex);\r\n } else if (e.key === 'Escape') {\r\n e.stopPropagation();\r\n this.cancel();\r\n }\r\n };\r\n window.addEventListener('keydown', this.keyHandler, { capture: true });\r\n }\r\n\r\n private detachKeyListener(): void {\r\n if (this.keyHandler) {\r\n window.removeEventListener('keydown', this.keyHandler, { capture: true });\r\n this.keyHandler = null;\r\n }\r\n }\r\n\r\n // ββ Row click listeners βββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private attachRowClickListeners(): void {\r\n this.shadow.querySelectorAll('[data-idx]').forEach((row) => {\r\n (row as HTMLElement).addEventListener('click', () => {\r\n const idx = parseInt((row as HTMLElement).dataset['idx'] ?? '0', 10);\r\n this.confirm(idx);\r\n });\r\n });\r\n }\r\n\r\n // ββ Recording auto-close ββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private subscribeToRecordingChanges(): void {\r\n this.unsubRecording = this.recording.onRecordingChange((isRecording) => {\r\n if (!isRecording) this.closeSilently();\r\n });\r\n this.unsubPause = this.recording.onPauseChange((isPaused) => {\r\n if (isPaused) this.closeSilently();\r\n });\r\n }\r\n\r\n // ββ Actions βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private confirm(index: number): void {\r\n const row = this.rows[index];\r\n if (!row) return;\r\n const command = `cy.get('${row.selector}').click()`;\r\n this.recording.appendCommand(command);\r\n this.dispatchEvent(new CustomEvent('selectorchosen', { detail: command, bubbles: true, composed: true }));\r\n this.closeSilently();\r\n }\r\n\r\n private cancel(): void {\r\n this.dispatchEvent(new CustomEvent('pickercancelled', { bubbles: true, composed: true }));\r\n this.closeSilently();\r\n }\r\n\r\n private closeSilently(): void {\r\n this.detachKeyListener();\r\n this.unsubRecording?.();\r\n this.unsubPause?.();\r\n this.unsubRecording = null;\r\n this.unsubPause = null;\r\n this.remove();\r\n }\r\n}\r\n\r\nif (!customElements.get('selector-picker')) {\r\n customElements.define('selector-picker', SelectorPickerElement);\r\n}\r\n","// Public API β populated as migration phases are completed\r\n// Keep in sync with package.json \"version\" (asserted in specs/public-api.spec.ts).\r\nexport const VERSION = '0.6.0';\r\n\r\n// Phase 1 β Models\r\nexport * from './models/lang.model';\r\nexport * from './models/input-types.model';\r\nexport * from './models/db-schema.model';\r\nexport * from './models/active-session.model';\r\n\r\n// Phase 2 β TranslationService\r\nexport * from './services/translation.service';\r\n\r\n// Phase 3 β Transformation Services\r\nexport * from './services/transformation.service';\r\nexport * from './services/advanced-test.transformation.service';\r\n\r\n// Phase 4 β RecordingService\r\nexport * from './utils/subject';\r\nexport * from './services/recording.service';\r\n\r\n// Phase 5 β PersistenceService\r\nexport * from './services/persistence.service';\r\n\r\n// Phase 6 β HttpMonitor\r\nexport * from './services/http-monitor';\r\n\r\n// Phase 7 β UI Utilities\r\nexport * from './utils/styles.utils';\r\nexport * from './utils/modal.utils';\r\nexport * from './utils/toast.utils';\r\nexport * from './utils/export-selection.utils';\r\nexport * from './utils/host.utils';\r\nexport * from './utils/widget-position.utils';\r\n\r\n// Phase 8 β Web Components\r\nexport * from './components/selector-picker/selector-picker';\r\nexport * from './components/test-previsualizer/test-previsualizer';\r\nexport * from './components/save-test/save-test';\r\nexport * from './components/test-editor/test-editor';\r\nexport * from './components/configuration/configuration';\r\nexport * from './components/advanced-test-editor/advanced-test-editor';\r\nexport * from './components/file-preview/file-preview';\r\nexport * from './components/lib-e2e-recorder/lib-e2e-recorder';\r\n","export type Lang = 'es' | 'en' | 'fr' | 'it' | 'de';\r\n\r\nexport const SUPPORTED_LANGS: Lang[] = ['es', 'en', 'fr', 'it', 'de'];\r\n\r\nexport function isLang(value: string): value is Lang {\r\n return SUPPORTED_LANGS.includes(value as Lang);\r\n}\r\n\r\n/** BCP-47 locale used for date/number formatting per UI language. */\r\nexport const LOCALE_BY_LANG: Record<Lang, string> = {\r\n es: 'es-ES',\r\n en: 'en-GB',\r\n fr: 'fr-FR',\r\n it: 'it-IT',\r\n de: 'de-DE',\r\n};\r\n\r\n/** Returns the formatting locale for a UI language (falls back to es-ES). */\r\nexport function localeForLang(lang: string): string {\r\n return isLang(lang) ? LOCALE_BY_LANG[lang] : 'es-ES';\r\n}\r\n","export const INPUT_TYPES = [\r\n 'text',\r\n 'password',\r\n 'email',\r\n 'search',\r\n 'tel',\r\n 'url',\r\n 'number',\r\n 'textarea',\r\n] as const;\r\n\r\nexport type InputType = (typeof INPUT_TYPES)[number];\r\n","export interface DBStoreIndex {\r\n name: string;\r\n keyPath: string;\r\n unique: boolean;\r\n}\r\n\r\nexport interface DBStore {\r\n name: string;\r\n keyPath: string;\r\n autoIncrement: boolean;\r\n indexes: DBStoreIndex[];\r\n}\r\n\r\nexport interface DBSchema {\r\n name: string;\r\n version: number;\r\n stores: DBStore[];\r\n}\r\n\r\nexport const DB_SCHEMA: DBSchema = {\r\n name: 'E2ECypressDB',\r\n version: 11,\r\n stores: [\r\n {\r\n name: 'tests',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'name', keyPath: 'name', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'commands',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'command', keyPath: 'command', unique: false },\r\n { name: 'testId', keyPath: 'testId', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'interceptors',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'interceptor', keyPath: 'interceptor', unique: false },\r\n { name: 'testId', keyPath: 'testId', unique: false },\r\n { name: 'createdAt', keyPath: 'createdAt', unique: false },\r\n ],\r\n },\r\n {\r\n name: 'configuration',\r\n keyPath: 'id',\r\n autoIncrement: true,\r\n indexes: [\r\n { name: 'language', keyPath: 'language', unique: false },\r\n { name: 'extendedHttpCommands', keyPath: 'extendedHttpCommands', unique: false },\r\n { name: 'allowReadWriteFiles', keyPath: 'allowReadWriteFiles', unique: false },\r\n ],\r\n },\r\n {\r\n // Single-record store (fixed key id=1) holding the live, in-progress\r\n // recording session so it survives a micro-frontend crossing or reload.\r\n // See docs/specs/006-cross-app-recording-continuity.md.\r\n name: 'activeSession',\r\n keyPath: 'id',\r\n autoIncrement: false,\r\n indexes: [],\r\n },\r\n ],\r\n};\r\n\r\nexport const DB_STORE_NAMES = DB_SCHEMA.stores.map(s => s.name) as [\r\n 'tests',\r\n 'commands',\r\n 'interceptors',\r\n 'configuration',\r\n 'activeSession',\r\n];\r\n","import type { SelectorStrategy } from '../services/recording.service';\r\n\r\n/**\r\n * A live, in-progress recording session, persisted so it can survive a\r\n * micro-frontend crossing (single-spa app swap) or an accidental same-origin\r\n * reload. Only an actively-recording session is ever stored/resumed.\r\n *\r\n * The full payload lives in IndexedDB; a lightweight breadcrumb (sessionId +\r\n * isRecording + updatedAt) is mirrored to localStorage for synchronous detection.\r\n *\r\n * See docs/specs/006-cross-app-recording-continuity.md.\r\n */\r\nexport interface ActiveSessionState {\r\n /** Stable id for the session, generated when recording starts. */\r\n sessionId: string;\r\n isRecording: boolean;\r\n isPaused: boolean;\r\n commands: string[];\r\n interceptors: string[];\r\n selectorStrategy: SelectorStrategy;\r\n /** Epoch ms when the session started recording. */\r\n startedAt: number;\r\n /** Epoch ms of the last mutation β acts as the recency heartbeat. */\r\n updatedAt: number;\r\n}\r\n\r\n/** localStorage key for the synchronous \"is a session active?\" breadcrumb. */\r\nexport const ACTIVE_SESSION_BREADCRUMB_KEY = 'e2e-active-session';\r\n\r\n/** Configuration key (in the `configuration` store) for the resume recency TTL. */\r\nexport const RESUME_TTL_CONFIG_KEY = 'resumeRecencyTtlMinutes';\r\n\r\n/** Default minutes within which an active session resumes silently. */\r\nexport const DEFAULT_RESUME_TTL_MINUTES = 30;\r\n","export class Subject<T> {\r\n private _value: T;\r\n private listeners = new Set<(v: T) => void>();\r\n\r\n constructor(initialValue: T) {\r\n this._value = initialValue;\r\n }\r\n\r\n next(value: T): void {\r\n this._value = value;\r\n this.listeners.forEach((l) => l(value));\r\n }\r\n\r\n getValue(): T {\r\n return this._value;\r\n }\r\n\r\n subscribe(fn: (v: T) => void): () => void {\r\n this.listeners.add(fn);\r\n return () => this.listeners.delete(fn);\r\n }\r\n}\r\n","export const I18N_ES = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'ConfiguraciΓ³n',\r\n SHOW_ADVANCED_EDITOR: 'Editor avanzado',\r\n DIALOG_SAVED_TESTS: 'Pruebas guardadas',\r\n DIALOG_COMMANDS: 'Previsualizador de comandos Cypress',\r\n DIALOG_SAVE: 'ΒΏGuardar la grabaciΓ³n?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'DescripciΓ³n de la prueba',\r\n CANCEL: 'Cancelar',\r\n ASK: 'ΒΏGuardar el test grabado?',\r\n YES_CONTINUE: 'SΓ, continuar',\r\n NO_DISCARD: 'No, descartar',\r\n DESC_PLACEHOLDER: 'Ej: Login correcto con credenciales vΓ‘lidas',\r\n TAGS_LABEL: 'Etiquetas (opcional, para filtrar despuΓ©s):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regresiΓ³nβ¦',\r\n ADD_TAG: '+ AΓ±adir',\r\n NO_TAGS: 'Sin etiquetas',\r\n SAVE_BTN: 'πΎ Guardar',\r\n SAVE_AND_EDIT: 'π Guardar y editar',\r\n REMOVE_TAG_TITLE: 'Quitar',\r\n NOTES_LABEL: 'DescripciΓ³n / Notas (opcional):',\r\n NOTES_PLACEHOLDER: 'QuΓ© valida este test, condiciones previas, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Sin etiquetas',\r\n SELECTED_SINGULAR: 'seleccionado',\r\n SELECTED_PLURAL: 'seleccionados',\r\n DESCRIBE_PLACEHOLDER: 'Nombre del describe (opcional)',\r\n COPY_DESCRIBE: 'π Copiar describe()',\r\n MULTI_SELECT: 'π Multi-select',\r\n CANCEL_SELECT: 'β Cancelar',\r\n COPY_CMDS_BTN: 'π Copiar comandos',\r\n COPY_ICPS_BTN: 'π Copiar interceptores',\r\n DEFAULT_DESCRIBE: 'Suite de tests',\r\n NO_TESTS: 'No hay tests guardados',\r\n DELETE_TITLE: 'Eliminar',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Idioma',\r\n LANG_FIELD: 'Interfaz',\r\n HTTP_SECTION: 'β‘ HTTP Avanzado',\r\n HTTP_TITLE: 'Validaciones de body',\r\n HTTP_SUB: 'GET β response Β· POST/PUT β request',\r\n SELECTOR_SECTION: 'π― Estrategia de selector',\r\n SELECTOR_LABEL: 'Atributo preferido para cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (por defecto)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#elemento)',\r\n SELECTOR_HINT: 'El grabador buscarΓ‘ este atributo primero. Si no existe, intentarΓ‘ los demΓ‘s.',\r\n FOLDER_SECTION: 'π Carpeta Cypress',\r\n FOLDER_CONNECTED: 'conectado β',\r\n FOLDER_NOT_SET: 'sin configurar',\r\n FOLDER_CHANGE_BTN: 'π Cambiar carpeta',\r\n FOLDER_SELECT_BTN: 'π Seleccionar carpeta',\r\n FOLDER_REVOKE_BTN: 'β Quitar acceso',\r\n DATA_SECTION: 'πΎ Datos',\r\n DATA_DESC: 'Exporta todos tus tests a JSON o importa una copia de seguridad.',\r\n EXPORT_BTN: 'β¬οΈ Exportar tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Exportar tests',\r\n EXPORT_MODE_ALL: 'Todo',\r\n EXPORT_MODE_MANUAL: 'SelecciΓ³n manual',\r\n EXPORT_MODE_TAGS: 'Por tags',\r\n EXPORT_ALL_DESC: 'Se exportarΓ‘n todos los tests guardados.',\r\n EXPORT_COUNT: 'A exportar:',\r\n EXPORT_CONFIRM: 'β¬οΈ Exportar',\r\n EXPORT_CANCEL: 'Cancelar',\r\n EXPORT_EMPTY: 'No hay tests para exportar.',\r\n EXPORT_NO_TAGS: 'No hay tags disponibles.',\r\n EXPORT_TAGS_HINT: 'Selecciona uno o mΓ‘s tags para ver quΓ© pruebas se exportarΓ‘n.',\r\n EXPORT_RESULT_LABEL: 'Pruebas que se exportarΓ‘n:',\r\n IMPORT_BTN: 'β¬οΈ Importar tests',\r\n FOLDER_UPDATED_TOAST: 'β Carpeta de Cypress actualizada',\r\n FOLDER_ERROR_TOAST: 'Error al acceder a la carpeta',\r\n IMPORT_SUCCESS: 'Datos importados correctamente.',\r\n IMPORT_ERROR: 'Error al importar.',\r\n JSON_INVALID: 'El archivo no es un JSON vΓ‘lido.',\r\n JSON_BAD_FORMAT: 'El archivo no tiene el formato esperado.',\r\n SMART_SELECTOR_SECTION: 'π Selector inteligente',\r\n SMART_SELECTOR_TITLE: 'Selector inteligente',\r\n SMART_SELECTOR_SUB: 'Muestra un picker al hacer click en elementos sin selector vΓ‘lido.',\r\n START_HIDDEN_SECTION: 'π Visibilidad del widget',\r\n START_HIDDEN_TITLE: 'Iniciar oculto',\r\n START_HIDDEN_SUB: 'El widget arranca invisible. Usa Ctrl+Shift+E para mostrarlo u ocultarlo.',\r\n RESUME_TTL_SECTION: 'β± Continuidad de grabaciΓ³n',\r\n RESUME_TTL_LABEL: 'Reanudar sin preguntar (minutos)',\r\n RESUME_TTL_HINT: 'Si recargas o cambias de proyecto, una grabaciΓ³n activa se reanuda sin preguntar dentro de este margen. Pasado ese tiempo, te preguntarΓ‘ si continuar o descartar.',\r\n WIDGET_POSITION_SECTION: 'π§² PosiciΓ³n del widget',\r\n WIDGET_POSITION_HINT: 'Arrastra el botΓ³n de grabar para moverlo donde no estorbe. Se recuerda su posiciΓ³n.',\r\n WIDGET_POSITION_RESET_BTN: 'βΊ Restablecer posiciΓ³n',\r\n WIDGET_POSITION_RESET_DONE: 'β PosiciΓ³n restablecida',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Selecciona un elemento del DOM',\r\n PREVIEW_LABEL: 'navegar',\r\n CONFIRM_HINT: 'confirmar',\r\n CANCEL_HINT: 'cancelar',\r\n QUALITY_EXCELLENT: 'Excelente β tiene atributo de prueba (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Bueno β tiene un id vΓ‘lido',\r\n QUALITY_ACCEPTABLE: 'Aceptable β solo tiene clases CSS',\r\n QUALITY_POOR: 'No recomendado β solo tag o estilo inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptores',\r\n COPY_CMDS_BTN: 'π Copiar comandos',\r\n SHOW_INTERCEPTORS: 'βΌ Ver interceptores',\r\n HIDE_INTERCEPTORS: 'β² Ocultar interceptores',\r\n SECTION_COMMANDS: 'Comandos',\r\n NO_CMDS_YET: 'Sin comandos aΓΊn',\r\n NO_ICP_SHORT: 'Sin interceptores',\r\n COPY_ICP_BTN: 'π Copiar interceptores',\r\n UP_TITLE: 'Subir',\r\n DOWN_TITLE: 'Bajar',\r\n DEL_TITLE: 'Eliminar',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Reactivar acceso',\r\n PERMISSION_EXPIRED: 'π El permiso ha caducado',\r\n PERMISSION_EXPIRED_HINT: 'Haz clic para reactivar el acceso a tu carpeta de Cypress.',\r\n NO_ACCESS: 'π Sin acceso a archivos locales',\r\n NO_ACCESS_HINT: 'Configura el acceso en βοΈ Config.',\r\n NO_FILES: 'Sin archivos',\r\n SELECT_FILE: 'β Selecciona un archivo del Γ‘rbol',\r\n IT_LABEL: 'π§ͺ it() a insertar:',\r\n COPY_IT_BTN: 'π Copiar it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptores:',\r\n COPY_ICP_BTN: 'π Copiar interceptores',\r\n INSERT_BTN: 'πΎ Insertar en archivo',\r\n EDIT_MANUAL_BTN: 'βοΈ Editar manualmente',\r\n CLOSE_BTN: 'β Cerrar',\r\n NEW_FILE_BTN: '+ Nuevo archivo',\r\n NEW_FOLDER_BTN: '+ Nueva carpeta',\r\n REFRESH_BTN: 'β» Actualizar',\r\n NEW_FILE_PLACEHOLDER: 'nombre-del-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nombre-de-carpeta',\r\n NEW_FILE_CONFIRM: 'Crear',\r\n NEW_FILE_CANCEL: 'Cancelar',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Sin archivo',\r\n COPY_TITLE: 'Copiar contenido del editor',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copiar',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'Sin cambios respecto al original',\r\n NO_CHANGES_SHORT: 'Sin cambios',\r\n LAUNCH_BTN: 'βΆ Lanzar test',\r\n LAUNCH_LOCAL_ONLY: 'MuΓ©velo a local para poder probar',\r\n LAUNCH_RUNNING: 'β³ Ejecutandoβ¦',\r\n LAUNCH_PASSED: 'β Prueba superada',\r\n LAUNCH_FAILED: 'β Prueba fallida',\r\n LAUNCH_NO_RUNNER: 'No se detectΓ³ el runner local (ΒΏlo has arrancado?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Guardar',\r\n CLOSE_BTN: 'β Cerrar',\r\n BACK_TO_EDITOR: 'β Volver al editor',\r\n INSERT_BTN: 'πͺ Insertar bloques',\r\n INSERT_TITLE: 'Insertar it() y beforeEach() en el contenido del editor',\r\n INSERT_DONE: 'Bloques insertados en el editor',\r\n INSERT_ERROR: 'No se encontrΓ³ un bloque describe() vΓ‘lido en el archivo',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Acceso a ficheros',\r\n FS_LATER_BTN: 'Ahora no',\r\n FS_SELECT_BTN: 'π Seleccionar carpeta',\r\n FS_SUCCESS_TOAST: 'β Carpeta de Cypress configurada',\r\n FS_ERROR_TOAST: 'Error al acceder a la carpeta',\r\n FS_INTRO_HTML: 'El <strong style=\"color:#e6edf3\">editor avanzado</strong> puede insertar tus tests directamente en los archivos <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> de Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'Selecciona la carpeta que contiene la subcarpeta <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. La extensiΓ³n espera esta estructura:',\r\n FS_TREE_PICK_HINT: 'β selecciona esta carpeta',\r\n FS_TREE_READ_HINT: 'β la extensiΓ³n leerΓ‘ aquΓ',\r\n FS_PERMISSION_NOTE: 'El permiso se guarda en el navegador y no se vuelve a solicitar.',\r\n ASSERTION_SECTION: 'β AΓ±adir aserciΓ³n',\r\n ASSERT_SELECTOR_PH: 'selector, ej: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valor esperado',\r\n ASSERT_ADD_BTN: 'β AΓ±adir',\r\n FILE_EDITOR_TITLE: 'βοΈ Editor de archivo',\r\n FILE_SAVED_TOAST: 'β Archivo guardado',\r\n FILE_SAVE_ERROR_TOAST: 'Error al guardar el archivo',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Ficheros',\r\n BTN_COMMANDS: 'Comandos',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pausar (Ctrl+P)',\r\n RESUME_TITLE: 'Reanudar (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSA',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Detener (Ctrl+R)',\r\n START_TITLE: 'Grabar (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ GrabaciΓ³n en curso',\r\n SESSION_RESUME_TEXT: 'Hay una grabaciΓ³n activa sin terminar.',\r\n SESSION_RESUME_COUNT: 'comandos capturados',\r\n SESSION_CONTINUE_BTN: 'Continuar grabando',\r\n SESSION_DISCARD_BTN: 'Descartar',\r\n },\r\n};\r\n","export const I18N_EN = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Settings',\r\n SHOW_ADVANCED_EDITOR: 'Advanced editor',\r\n DIALOG_SAVED_TESTS: 'Saved tests',\r\n DIALOG_COMMANDS: 'Cypress commands previewer',\r\n DIALOG_SAVE: 'Save recording?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Test description',\r\n CANCEL: 'Cancel',\r\n ASK: 'Save the recorded test?',\r\n YES_CONTINUE: 'Yes, continue',\r\n NO_DISCARD: 'No, discard',\r\n DESC_PLACEHOLDER: 'E.g.: Successful login with valid credentials',\r\n TAGS_LABEL: 'Tags (optional, for later filtering):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressionβ¦',\r\n ADD_TAG: '+ Add',\r\n NO_TAGS: 'No tags',\r\n SAVE_BTN: 'πΎ Save',\r\n SAVE_AND_EDIT: 'π Save and edit',\r\n REMOVE_TAG_TITLE: 'Remove',\r\n NOTES_LABEL: 'Description / Notes (optional):',\r\n NOTES_PLACEHOLDER: 'What this test validates, preconditions, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'No tags',\r\n SELECTED_SINGULAR: 'selected',\r\n SELECTED_PLURAL: 'selected',\r\n DESCRIBE_PLACEHOLDER: 'describe name (optional)',\r\n COPY_DESCRIBE: 'π Copy describe()',\r\n MULTI_SELECT: 'π Multi-select',\r\n CANCEL_SELECT: 'β Cancel',\r\n COPY_CMDS_BTN: 'π Copy commands',\r\n COPY_ICPS_BTN: 'π Copy interceptors',\r\n DEFAULT_DESCRIBE: 'Test suite',\r\n NO_TESTS: 'No saved tests',\r\n DELETE_TITLE: 'Delete',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Language',\r\n LANG_FIELD: 'Interface',\r\n HTTP_SECTION: 'β‘ Advanced HTTP',\r\n HTTP_TITLE: 'Body validations',\r\n HTTP_SUB: 'GET β response Β· POST/PUT β request',\r\n SELECTOR_SECTION: 'π― Selector strategy',\r\n SELECTOR_LABEL: 'Preferred attribute for cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (default)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#element)',\r\n SELECTOR_HINT: 'The recorder will look for this attribute first. If not found, it will try the others.',\r\n FOLDER_SECTION: 'π Cypress Folder',\r\n FOLDER_CONNECTED: 'connected β',\r\n FOLDER_NOT_SET: 'not configured',\r\n FOLDER_CHANGE_BTN: 'π Change folder',\r\n FOLDER_SELECT_BTN: 'π Select folder',\r\n FOLDER_REVOKE_BTN: 'β Revoke access',\r\n DATA_SECTION: 'πΎ Data',\r\n DATA_DESC: 'Export all your tests to JSON or import a backup.',\r\n EXPORT_BTN: 'β¬οΈ Export tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Export tests',\r\n EXPORT_MODE_ALL: 'All',\r\n EXPORT_MODE_MANUAL: 'Manual selection',\r\n EXPORT_MODE_TAGS: 'By tags',\r\n EXPORT_ALL_DESC: 'All saved tests will be exported.',\r\n EXPORT_COUNT: 'To export:',\r\n EXPORT_CONFIRM: 'β¬οΈ Export',\r\n EXPORT_CANCEL: 'Cancel',\r\n EXPORT_EMPTY: 'No tests to export.',\r\n EXPORT_NO_TAGS: 'No tags available.',\r\n EXPORT_TAGS_HINT: 'Select one or more tags to preview which tests will be exported.',\r\n EXPORT_RESULT_LABEL: 'Tests that will be exported:',\r\n IMPORT_BTN: 'β¬οΈ Import tests',\r\n FOLDER_UPDATED_TOAST: 'β Cypress folder updated',\r\n FOLDER_ERROR_TOAST: 'Error accessing the folder',\r\n IMPORT_SUCCESS: 'Data imported successfully.',\r\n IMPORT_ERROR: 'Error importing.',\r\n JSON_INVALID: 'The file is not valid JSON.',\r\n JSON_BAD_FORMAT: 'The file does not have the expected format.',\r\n SMART_SELECTOR_SECTION: 'π Smart selector',\r\n SMART_SELECTOR_TITLE: 'Smart selector',\r\n SMART_SELECTOR_SUB: 'Shows a picker when clicking elements with no valid selector.',\r\n START_HIDDEN_SECTION: 'π Widget visibility',\r\n START_HIDDEN_TITLE: 'Start hidden',\r\n START_HIDDEN_SUB: 'The widget starts invisible. Use Ctrl+Shift+E to show or hide it.',\r\n RESUME_TTL_SECTION: 'β± Recording continuity',\r\n RESUME_TTL_LABEL: 'Resume without asking (minutes)',\r\n RESUME_TTL_HINT: 'If you reload or switch projects, an active recording resumes without asking within this window. After that, you will be asked to continue or discard.',\r\n WIDGET_POSITION_SECTION: 'π§² Widget position',\r\n WIDGET_POSITION_HINT: 'Drag the record button to move it out of the way. Its position is remembered.',\r\n WIDGET_POSITION_RESET_BTN: 'βΊ Reset position',\r\n WIDGET_POSITION_RESET_DONE: 'β Position reset',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Select a DOM element',\r\n PREVIEW_LABEL: 'navigate',\r\n CONFIRM_HINT: 'confirm',\r\n CANCEL_HINT: 'cancel',\r\n QUALITY_EXCELLENT: 'Excellent β has a testing attribute (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Good β has a valid id',\r\n QUALITY_ACCEPTABLE: 'Acceptable β CSS classes only',\r\n QUALITY_POOR: 'Not recommended β tag name or inline style only',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptors',\r\n COPY_CMDS_BTN: 'π Copy commands',\r\n SHOW_INTERCEPTORS: 'βΌ Show interceptors',\r\n HIDE_INTERCEPTORS: 'β² Hide interceptors',\r\n SECTION_COMMANDS: 'Commands',\r\n NO_CMDS_YET: 'No commands yet',\r\n NO_ICP_SHORT: 'No interceptors',\r\n COPY_ICP_BTN: 'π Copy interceptors',\r\n UP_TITLE: 'Move up',\r\n DOWN_TITLE: 'Move down',\r\n DEL_TITLE: 'Delete',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Reactivate access',\r\n PERMISSION_EXPIRED: 'π Permission expired',\r\n PERMISSION_EXPIRED_HINT: 'Click to reactivate access to your Cypress folder.',\r\n NO_ACCESS: 'π No access to local files',\r\n NO_ACCESS_HINT: 'Configure access in βοΈ Config.',\r\n NO_FILES: 'No files',\r\n SELECT_FILE: 'β Select a file from the tree',\r\n IT_LABEL: 'π§ͺ it() to insert:',\r\n COPY_IT_BTN: 'π Copy it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptors:',\r\n COPY_ICP_BTN: 'π Copy interceptors',\r\n INSERT_BTN: 'πΎ Insert into file',\r\n EDIT_MANUAL_BTN: 'βοΈ Edit manually',\r\n CLOSE_BTN: 'β Close',\r\n NEW_FILE_BTN: '+ New file',\r\n NEW_FOLDER_BTN: '+ New folder',\r\n REFRESH_BTN: 'β» Refresh',\r\n NEW_FILE_PLACEHOLDER: 'test-name',\r\n NEW_FOLDER_PLACEHOLDER: 'folder-name',\r\n NEW_FILE_CONFIRM: 'Create',\r\n NEW_FILE_CANCEL: 'Cancel',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'No file',\r\n COPY_TITLE: 'Copy editor content',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copy',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'No changes from original',\r\n NO_CHANGES_SHORT: 'No changes',\r\n LAUNCH_BTN: 'βΆ Run test',\r\n LAUNCH_LOCAL_ONLY: 'Move it to localhost to run tests',\r\n LAUNCH_RUNNING: 'β³ Runningβ¦',\r\n LAUNCH_PASSED: 'β Test passed',\r\n LAUNCH_FAILED: 'β Test failed',\r\n LAUNCH_NO_RUNNER: 'No local runner detected (did you start it?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Save',\r\n CLOSE_BTN: 'β Close',\r\n BACK_TO_EDITOR: 'β Back to editor',\r\n INSERT_BTN: 'πͺ Insert blocks',\r\n INSERT_TITLE: 'Insert it() and beforeEach() into the editor content',\r\n INSERT_DONE: 'Blocks inserted into the editor',\r\n INSERT_ERROR: 'No valid describe() block found in the file',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π File access',\r\n FS_LATER_BTN: 'Not now',\r\n FS_SELECT_BTN: 'π Select folder',\r\n FS_SUCCESS_TOAST: 'β Cypress folder configured',\r\n FS_ERROR_TOAST: 'Error accessing the folder',\r\n FS_INTRO_HTML: 'The <strong style=\"color:#e6edf3\">advanced editor</strong> can insert your tests directly into the Cypress <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> files.',\r\n FS_STRUCTURE_HINT_HTML: 'Select the folder that contains the <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code> subfolder. The extension expects this structure:',\r\n FS_TREE_PICK_HINT: 'β select this folder',\r\n FS_TREE_READ_HINT: 'β the extension will read here',\r\n FS_PERMISSION_NOTE: 'The permission is stored in the browser and will not be requested again.',\r\n ASSERTION_SECTION: 'β Add assertion',\r\n ASSERT_SELECTOR_PH: 'selector, e.g.: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'expected value',\r\n ASSERT_ADD_BTN: 'β Add',\r\n FILE_EDITOR_TITLE: 'βοΈ File editor',\r\n FILE_SAVED_TOAST: 'β File saved',\r\n FILE_SAVE_ERROR_TOAST: 'Error saving the file',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Files',\r\n BTN_COMMANDS: 'Commands',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pause (Ctrl+P)',\r\n RESUME_TITLE: 'Resume (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSED',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Stop (Ctrl+R)',\r\n START_TITLE: 'Record (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Recording in progress',\r\n SESSION_RESUME_TEXT: 'There is an unfinished active recording.',\r\n SESSION_RESUME_COUNT: 'commands captured',\r\n SESSION_CONTINUE_BTN: 'Keep recording',\r\n SESSION_DISCARD_BTN: 'Discard',\r\n },\r\n};\r\n","export const I18N_FR = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'ParamΓ¨tres',\r\n SHOW_ADVANCED_EDITOR: 'Γditeur avancΓ©',\r\n DIALOG_SAVED_TESTS: 'Tests enregistrΓ©s',\r\n DIALOG_COMMANDS: 'AperΓ§u des commandes Cypress',\r\n DIALOG_SAVE: \"Enregistrer l'enregistrement ?\",\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Description du test',\r\n CANCEL: 'Annuler',\r\n ASK: 'Enregistrer le test ?',\r\n YES_CONTINUE: 'Oui, continuer',\r\n NO_DISCARD: 'Non, ignorer',\r\n DESC_PLACEHOLDER: 'Ex : Connexion rΓ©ussie avec identifiants valides',\r\n TAGS_LABEL: 'Γtiquettes (optionnel, pour filtrer ensuite) :',\r\n TAGS_PLACEHOLDER: 'smoke, login, rΓ©gressionβ¦',\r\n ADD_TAG: '+ Ajouter',\r\n NO_TAGS: 'Sans Γ©tiquettes',\r\n SAVE_BTN: 'πΎ Enregistrer',\r\n SAVE_AND_EDIT: 'π Enregistrer et Γ©diter',\r\n REMOVE_TAG_TITLE: 'Retirer',\r\n NOTES_LABEL: 'Description / Notes (optionnel) :',\r\n NOTES_PLACEHOLDER: 'Ce que ce test valide, conditions prΓ©alables, etc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Sans Γ©tiquettes',\r\n SELECTED_SINGULAR: 'sΓ©lectionnΓ©',\r\n SELECTED_PLURAL: 'sΓ©lectionnΓ©s',\r\n DESCRIBE_PLACEHOLDER: 'Nom du describe (optionnel)',\r\n COPY_DESCRIBE: 'π Copier describe()',\r\n MULTI_SELECT: 'π Multi-sΓ©lection',\r\n CANCEL_SELECT: 'β Annuler',\r\n COPY_CMDS_BTN: 'π Copier les commandes',\r\n COPY_ICPS_BTN: 'π Copier les intercepteurs',\r\n DEFAULT_DESCRIBE: 'Suite de tests',\r\n NO_TESTS: 'Aucun test enregistrΓ©',\r\n DELETE_TITLE: 'Supprimer',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Langue',\r\n LANG_FIELD: 'Interface',\r\n HTTP_SECTION: 'β‘ HTTP AvancΓ©',\r\n HTTP_TITLE: 'Validations du corps',\r\n HTTP_SUB: 'GET β rΓ©ponse Β· POST/PUT β requΓͺte',\r\n SELECTOR_SECTION: 'π― StratΓ©gie de sΓ©lecteur',\r\n SELECTOR_LABEL: 'Attribut prΓ©fΓ©rΓ© pour cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (par dΓ©faut)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#Γ©lΓ©ment)',\r\n SELECTOR_HINT: \"L'enregistreur cherchera d'abord cet attribut. Si absent, il essaiera les autres.\",\r\n FOLDER_SECTION: 'π Dossier Cypress',\r\n FOLDER_CONNECTED: 'connectΓ© β',\r\n FOLDER_NOT_SET: 'non configurΓ©',\r\n FOLDER_CHANGE_BTN: 'π Changer de dossier',\r\n FOLDER_SELECT_BTN: 'π SΓ©lectionner un dossier',\r\n FOLDER_REVOKE_BTN: \"β RΓ©voquer l'accΓ¨s\",\r\n DATA_SECTION: 'πΎ DonnΓ©es',\r\n DATA_DESC: 'Exportez tous vos tests en JSON ou importez une sauvegarde.',\r\n EXPORT_BTN: 'β¬οΈ Exporter les tests',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Exporter les tests',\r\n EXPORT_MODE_ALL: 'Tout',\r\n EXPORT_MODE_MANUAL: 'SΓ©lection manuelle',\r\n EXPORT_MODE_TAGS: 'Par tags',\r\n EXPORT_ALL_DESC: 'Tous les tests enregistrΓ©s seront exportΓ©s.',\r\n EXPORT_COUNT: 'Γ exporter :',\r\n EXPORT_CONFIRM: 'β¬οΈ Exporter',\r\n EXPORT_CANCEL: 'Annuler',\r\n EXPORT_EMPTY: 'Aucun test Γ exporter.',\r\n EXPORT_NO_TAGS: 'Aucun tag disponible.',\r\n EXPORT_TAGS_HINT: 'SΓ©lectionnez un ou plusieurs tags pour voir les tests qui seront exportΓ©s.',\r\n EXPORT_RESULT_LABEL: 'Tests qui seront exportΓ©s :',\r\n IMPORT_BTN: 'β¬οΈ Importer les tests',\r\n FOLDER_UPDATED_TOAST: 'β Dossier Cypress mis Γ jour',\r\n FOLDER_ERROR_TOAST: \"Erreur lors de l'accΓ¨s au dossier\",\r\n IMPORT_SUCCESS: 'DonnΓ©es importΓ©es avec succΓ¨s.',\r\n IMPORT_ERROR: \"Erreur lors de l'importation.\",\r\n JSON_INVALID: \"Le fichier n'est pas un JSON valide.\",\r\n JSON_BAD_FORMAT: \"Le fichier n'a pas le format attendu.\",\r\n SMART_SELECTOR_SECTION: 'π SΓ©lecteur intelligent',\r\n SMART_SELECTOR_TITLE: 'SΓ©lecteur intelligent',\r\n SMART_SELECTOR_SUB: 'Affiche un sΓ©lecteur lors du clic sur des Γ©lΓ©ments sans sΓ©lecteur valide.',\r\n START_HIDDEN_SECTION: 'π VisibilitΓ© du widget',\r\n START_HIDDEN_TITLE: 'DΓ©marrer masquΓ©',\r\n START_HIDDEN_SUB: 'Le widget dΓ©marre invisible. Utilisez Ctrl+Shift+E pour l\\'afficher ou le masquer.',\r\n RESUME_TTL_SECTION: 'β± ContinuitΓ© d\\'enregistrement',\r\n RESUME_TTL_LABEL: 'Reprendre sans demander (minutes)',\r\n RESUME_TTL_HINT: 'Si vous rechargez ou changez de projet, un enregistrement actif reprend sans demander dans ce dΓ©lai. Au-delΓ , il vous demandera de continuer ou d\\'ignorer.',\r\n WIDGET_POSITION_SECTION: 'π§² Position du widget',\r\n WIDGET_POSITION_HINT: 'Fais glisser le bouton d\\'enregistrement pour le dΓ©placer. Sa position est mΓ©morisΓ©e.',\r\n WIDGET_POSITION_RESET_BTN: 'βΊ RΓ©initialiser la position',\r\n WIDGET_POSITION_RESET_DONE: 'β Position rΓ©initialisΓ©e',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'SΓ©lectionnez un Γ©lΓ©ment du DOM',\r\n PREVIEW_LABEL: 'naviguer',\r\n CONFIRM_HINT: 'confirmer',\r\n CANCEL_HINT: 'annuler',\r\n QUALITY_EXCELLENT: 'Excellent β attribut de test prΓ©sent (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Bon β id valide',\r\n QUALITY_ACCEPTABLE: 'Acceptable β classes CSS uniquement',\r\n QUALITY_POOR: 'DΓ©conseillΓ© β seulement le nom de balise ou style inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Intercepteurs',\r\n COPY_CMDS_BTN: 'π Copier les commandes',\r\n SHOW_INTERCEPTORS: 'βΌ Voir les intercepteurs',\r\n HIDE_INTERCEPTORS: 'β² Masquer les intercepteurs',\r\n SECTION_COMMANDS: 'Commandes',\r\n NO_CMDS_YET: 'Aucune commande encore',\r\n NO_ICP_SHORT: 'Aucun intercepteur',\r\n COPY_ICP_BTN: 'π Copier les intercepteurs',\r\n UP_TITLE: 'Monter',\r\n DOWN_TITLE: 'Descendre',\r\n DEL_TITLE: 'Supprimer',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: \"π RΓ©activer l'accΓ¨s\",\r\n PERMISSION_EXPIRED: 'π Autorisation expirΓ©e',\r\n PERMISSION_EXPIRED_HINT: \"Cliquez pour rΓ©activer l'accΓ¨s Γ votre dossier Cypress.\",\r\n NO_ACCESS: 'π Pas d\\'accΓ¨s aux fichiers locaux',\r\n NO_ACCESS_HINT: \"Configurez l'accΓ¨s dans βοΈ Config.\",\r\n NO_FILES: 'Aucun fichier',\r\n SELECT_FILE: \"β SΓ©lectionnez un fichier dans l'arborescence\",\r\n IT_LABEL: 'π§ͺ it() Γ insΓ©rer :',\r\n COPY_IT_BTN: 'π Copier it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() intercepteurs :',\r\n COPY_ICP_BTN: 'π Copier les intercepteurs',\r\n INSERT_BTN: 'πΎ InsΓ©rer dans le fichier',\r\n EDIT_MANUAL_BTN: 'βοΈ Γditer manuellement',\r\n CLOSE_BTN: 'β Fermer',\r\n NEW_FILE_BTN: '+ Nouveau fichier',\r\n NEW_FOLDER_BTN: '+ Nouveau dossier',\r\n REFRESH_BTN: 'β» Actualiser',\r\n NEW_FILE_PLACEHOLDER: 'nom-du-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nom-du-dossier',\r\n NEW_FILE_CONFIRM: 'CrΓ©er',\r\n NEW_FILE_CANCEL: 'Annuler',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Sans fichier',\r\n COPY_TITLE: \"Copier le contenu de l'Γ©diteur\",\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copier',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: \"Aucun changement par rapport Γ l'original\",\r\n NO_CHANGES_SHORT: 'Aucun changement',\r\n LAUNCH_BTN: 'βΆ Lancer le test',\r\n LAUNCH_LOCAL_ONLY: 'Passe en local pour pouvoir tester',\r\n LAUNCH_RUNNING: 'β³ ExΓ©cutionβ¦',\r\n LAUNCH_PASSED: 'β Test rΓ©ussi',\r\n LAUNCH_FAILED: 'β Test Γ©chouΓ©',\r\n LAUNCH_NO_RUNNER: \"Aucun runner local dΓ©tectΓ© (l'avez-vous dΓ©marrΓ© ?)\",\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Enregistrer',\r\n CLOSE_BTN: 'β Fermer',\r\n BACK_TO_EDITOR: \"β Retour Γ l'Γ©diteur\",\r\n INSERT_BTN: 'πͺ InsΓ©rer les blocs',\r\n INSERT_TITLE: \"InsΓ©rer it() et beforeEach() dans le contenu de l'Γ©diteur\",\r\n INSERT_DONE: \"Blocs insΓ©rΓ©s dans l'Γ©diteur\",\r\n INSERT_ERROR: 'Aucun bloc describe() valide trouvΓ© dans le fichier',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π AccΓ¨s aux fichiers',\r\n FS_LATER_BTN: 'Pas maintenant',\r\n FS_SELECT_BTN: 'π SΓ©lectionner un dossier',\r\n FS_SUCCESS_TOAST: 'β Dossier Cypress configurΓ©',\r\n FS_ERROR_TOAST: \"Erreur lors de l'accΓ¨s au dossier\",\r\n FS_INTRO_HTML: 'L\\'<strong style=\"color:#e6edf3\">Γ©diteur avancΓ©</strong> peut insΓ©rer vos tests directement dans les fichiers <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> de Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'SΓ©lectionnez le dossier qui contient le sous-dossier <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. L\\'extension attend cette structure :',\r\n FS_TREE_PICK_HINT: 'β sΓ©lectionnez ce dossier',\r\n FS_TREE_READ_HINT: 'β l\\'extension lira ici',\r\n FS_PERMISSION_NOTE: 'L\\'autorisation est enregistrΓ©e dans le navigateur et ne sera plus demandΓ©e.',\r\n ASSERTION_SECTION: 'β Ajouter une assertion',\r\n ASSERT_SELECTOR_PH: 'sΓ©lecteur, ex : [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valeur attendue',\r\n ASSERT_ADD_BTN: 'β Ajouter',\r\n FILE_EDITOR_TITLE: 'βοΈ Γditeur de fichier',\r\n FILE_SAVED_TOAST: 'β Fichier enregistrΓ©',\r\n FILE_SAVE_ERROR_TOAST: \"Erreur lors de l'enregistrement\",\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Fichiers',\r\n BTN_COMMANDS: 'Commandes',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pause (Ctrl+P)',\r\n RESUME_TITLE: 'Reprendre (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSE',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'ArrΓͺter (Ctrl+R)',\r\n START_TITLE: 'Enregistrer (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Enregistrement en cours',\r\n SESSION_RESUME_TEXT: 'Un enregistrement actif est inachevΓ©.',\r\n SESSION_RESUME_COUNT: 'commandes capturΓ©es',\r\n SESSION_CONTINUE_BTN: 'Continuer l\\'enregistrement',\r\n SESSION_DISCARD_BTN: 'Ignorer',\r\n },\r\n};\r\n","export const I18N_IT = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Impostazioni',\r\n SHOW_ADVANCED_EDITOR: 'Editor avanzato',\r\n DIALOG_SAVED_TESTS: 'Test salvati',\r\n DIALOG_COMMANDS: 'Anteprima comandi Cypress',\r\n DIALOG_SAVE: 'Salvare la registrazione?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Descrizione del test',\r\n CANCEL: 'Annulla',\r\n ASK: 'Salvare il test registrato?',\r\n YES_CONTINUE: 'SΓ¬, continua',\r\n NO_DISCARD: 'No, annulla',\r\n DESC_PLACEHOLDER: 'Es: Login riuscito con credenziali valide',\r\n TAGS_LABEL: 'Etichette (opzionale, per filtrare dopo):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressioneβ¦',\r\n ADD_TAG: '+ Aggiungi',\r\n NO_TAGS: 'Nessuna etichetta',\r\n SAVE_BTN: 'πΎ Salva',\r\n SAVE_AND_EDIT: 'π Salva e modifica',\r\n REMOVE_TAG_TITLE: 'Rimuovi',\r\n NOTES_LABEL: 'Descrizione / Note (opzionale):',\r\n NOTES_PLACEHOLDER: 'Cosa valida questo test, condizioni preliminari, ecc.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Nessuna etichetta',\r\n SELECTED_SINGULAR: 'selezionato',\r\n SELECTED_PLURAL: 'selezionati',\r\n DESCRIBE_PLACEHOLDER: 'Nome del describe (opzionale)',\r\n COPY_DESCRIBE: 'π Copia describe()',\r\n MULTI_SELECT: 'π Multi-selezione',\r\n CANCEL_SELECT: 'β Annulla',\r\n COPY_CMDS_BTN: 'π Copia comandi',\r\n COPY_ICPS_BTN: 'π Copia interceptor',\r\n DEFAULT_DESCRIBE: 'Suite di test',\r\n NO_TESTS: 'Nessun test salvato',\r\n DELETE_TITLE: 'Elimina',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Lingua',\r\n LANG_FIELD: 'Interfaccia',\r\n HTTP_SECTION: 'β‘ HTTP Avanzato',\r\n HTTP_TITLE: 'Validazioni del body',\r\n HTTP_SUB: 'GET β risposta Β· POST/PUT β richiesta',\r\n SELECTOR_SECTION: 'π― Strategia selettore',\r\n SELECTOR_LABEL: 'Attributo preferito per cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (predefinito)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#elemento)',\r\n SELECTOR_HINT: 'Il registratore cercherΓ prima questo attributo. Se assente, proverΓ gli altri.',\r\n FOLDER_SECTION: 'π Cartella Cypress',\r\n FOLDER_CONNECTED: 'connesso β',\r\n FOLDER_NOT_SET: 'non configurato',\r\n FOLDER_CHANGE_BTN: 'π Cambia cartella',\r\n FOLDER_SELECT_BTN: 'π Seleziona cartella',\r\n FOLDER_REVOKE_BTN: 'β Revoca accesso',\r\n DATA_SECTION: 'πΎ Dati',\r\n DATA_DESC: 'Esporta tutti i tuoi test in JSON o importa un backup.',\r\n EXPORT_BTN: 'β¬οΈ Esporta test',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Esporta test',\r\n EXPORT_MODE_ALL: 'Tutto',\r\n EXPORT_MODE_MANUAL: 'Selezione manuale',\r\n EXPORT_MODE_TAGS: 'Per tag',\r\n EXPORT_ALL_DESC: 'Verranno esportati tutti i test salvati.',\r\n EXPORT_COUNT: 'Da esportare:',\r\n EXPORT_CONFIRM: 'β¬οΈ Esporta',\r\n EXPORT_CANCEL: 'Annulla',\r\n EXPORT_EMPTY: 'Nessun test da esportare.',\r\n EXPORT_NO_TAGS: 'Nessun tag disponibile.',\r\n EXPORT_TAGS_HINT: 'Seleziona uno o piΓΉ tag per vedere quali test verranno esportati.',\r\n EXPORT_RESULT_LABEL: 'Test che verranno esportati:',\r\n IMPORT_BTN: 'β¬οΈ Importa test',\r\n FOLDER_UPDATED_TOAST: 'β Cartella Cypress aggiornata',\r\n FOLDER_ERROR_TOAST: \"Errore durante l'accesso alla cartella\",\r\n IMPORT_SUCCESS: 'Dati importati correttamente.',\r\n IMPORT_ERROR: \"Errore durante l'importazione.\",\r\n JSON_INVALID: 'Il file non Γ¨ un JSON valido.',\r\n JSON_BAD_FORMAT: 'Il file non ha il formato previsto.',\r\n SMART_SELECTOR_SECTION: 'π Selettore intelligente',\r\n SMART_SELECTOR_TITLE: 'Selettore intelligente',\r\n SMART_SELECTOR_SUB: 'Mostra un selettore quando si fa clic su elementi senza selettore valido.',\r\n START_HIDDEN_SECTION: 'π VisibilitΓ del widget',\r\n START_HIDDEN_TITLE: 'Avvia nascosto',\r\n START_HIDDEN_SUB: 'Il widget si avvia invisibile. Usa Ctrl+Shift+E per mostrarlo o nasconderlo.',\r\n RESUME_TTL_SECTION: 'β± ContinuitΓ di registrazione',\r\n RESUME_TTL_LABEL: 'Riprendi senza chiedere (minuti)',\r\n RESUME_TTL_HINT: 'Se ricarichi o cambi progetto, una registrazione attiva riprende senza chiedere entro questo intervallo. Trascorso, ti chiederΓ se continuare o annullare.',\r\n WIDGET_POSITION_SECTION: 'π§² Posizione del widget',\r\n WIDGET_POSITION_HINT: 'Trascina il pulsante di registrazione per spostarlo. La posizione viene ricordata.',\r\n WIDGET_POSITION_RESET_BTN: 'βΊ Reimposta posizione',\r\n WIDGET_POSITION_RESET_DONE: 'β Posizione reimpostata',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'Seleziona un elemento DOM',\r\n PREVIEW_LABEL: 'navigare',\r\n CONFIRM_HINT: 'confermare',\r\n CANCEL_HINT: 'annullare',\r\n QUALITY_EXCELLENT: 'Eccellente β attributo di test presente (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Buono β id valido',\r\n QUALITY_ACCEPTABLE: 'Accettabile β solo classi CSS',\r\n QUALITY_POOR: 'Sconsigliato β solo tag o stile inline',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptor',\r\n COPY_CMDS_BTN: 'π Copia comandi',\r\n SHOW_INTERCEPTORS: 'βΌ Vedi interceptor',\r\n HIDE_INTERCEPTORS: 'β² Nascondi interceptor',\r\n SECTION_COMMANDS: 'Comandi',\r\n NO_CMDS_YET: 'Ancora nessun comando',\r\n NO_ICP_SHORT: 'Nessun interceptor',\r\n COPY_ICP_BTN: 'π Copia interceptor',\r\n UP_TITLE: 'Su',\r\n DOWN_TITLE: 'GiΓΉ',\r\n DEL_TITLE: 'Elimina',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Riattiva accesso',\r\n PERMISSION_EXPIRED: 'π Autorizzazione scaduta',\r\n PERMISSION_EXPIRED_HINT: \"Clicca per riattivare l'accesso alla cartella Cypress.\",\r\n NO_ACCESS: 'π Nessun accesso ai file locali',\r\n NO_ACCESS_HINT: \"Configura l'accesso in βοΈ Config.\",\r\n NO_FILES: 'Nessun file',\r\n SELECT_FILE: \"β Seleziona un file dall'albero\",\r\n IT_LABEL: 'π§ͺ it() da inserire:',\r\n COPY_IT_BTN: 'π Copia it()',\r\n BEFORE_EACH_LABEL: 'π beforeEach() interceptor:',\r\n COPY_ICP_BTN: 'π Copia interceptor',\r\n INSERT_BTN: 'πΎ Inserisci nel file',\r\n EDIT_MANUAL_BTN: 'βοΈ Modifica manualmente',\r\n CLOSE_BTN: 'β Chiudi',\r\n NEW_FILE_BTN: '+ Nuovo file',\r\n NEW_FOLDER_BTN: '+ Nuova cartella',\r\n REFRESH_BTN: 'β» Aggiorna',\r\n NEW_FILE_PLACEHOLDER: 'nome-del-test',\r\n NEW_FOLDER_PLACEHOLDER: 'nome-cartella',\r\n NEW_FILE_CONFIRM: 'Crea',\r\n NEW_FILE_CANCEL: 'Annulla',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Nessun file',\r\n COPY_TITLE: \"Copia il contenuto dell'editor\",\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Copia',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: \"Nessuna modifica rispetto all'originale\",\r\n NO_CHANGES_SHORT: 'Nessuna modifica',\r\n LAUNCH_BTN: 'βΆ Esegui test',\r\n LAUNCH_LOCAL_ONLY: 'Spostati in locale per poter testare',\r\n LAUNCH_RUNNING: 'β³ Esecuzioneβ¦',\r\n LAUNCH_PASSED: 'β Test superato',\r\n LAUNCH_FAILED: 'β Test fallito',\r\n LAUNCH_NO_RUNNER: \"Nessun runner locale rilevato (l'hai avviato?)\",\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Salva',\r\n CLOSE_BTN: 'β Chiudi',\r\n BACK_TO_EDITOR: \"β Torna all'editor\",\r\n INSERT_BTN: 'πͺ Inserisci blocchi',\r\n INSERT_TITLE: \"Inserisci it() e beforeEach() nel contenuto dell'editor\",\r\n INSERT_DONE: \"Blocchi inseriti nell'editor\",\r\n INSERT_ERROR: 'Nessun blocco describe() valido trovato nel file',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Accesso ai file',\r\n FS_LATER_BTN: 'Non ora',\r\n FS_SELECT_BTN: 'π Seleziona cartella',\r\n FS_SUCCESS_TOAST: 'β Cartella Cypress configurata',\r\n FS_ERROR_TOAST: \"Errore durante l'accesso alla cartella\",\r\n FS_INTRO_HTML: 'L\\'<strong style=\"color:#e6edf3\">editor avanzato</strong> puΓ² inserire i tuoi test direttamente nei file <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> di Cypress.',\r\n FS_STRUCTURE_HINT_HTML: 'Seleziona la cartella che contiene la sottocartella <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code>. L\\'estensione si aspetta questa struttura:',\r\n FS_TREE_PICK_HINT: 'β seleziona questa cartella',\r\n FS_TREE_READ_HINT: 'β l\\'estensione leggerΓ qui',\r\n FS_PERMISSION_NOTE: 'Il permesso viene salvato nel browser e non sarΓ richiesto di nuovo.',\r\n ASSERTION_SECTION: 'β Aggiungi asserzione',\r\n ASSERT_SELECTOR_PH: 'selettore, es: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'valore atteso',\r\n ASSERT_ADD_BTN: 'β Aggiungi',\r\n FILE_EDITOR_TITLE: 'βοΈ Editor di file',\r\n FILE_SAVED_TOAST: 'β File salvato',\r\n FILE_SAVE_ERROR_TOAST: 'Errore durante il salvataggio',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'File',\r\n BTN_COMMANDS: 'Comandi',\r\n BTN_TESTS: 'Test',\r\n PAUSE_TITLE: 'Pausa (Ctrl+P)',\r\n RESUME_TITLE: 'Riprendi (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSA',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Ferma (Ctrl+R)',\r\n START_TITLE: 'Registra (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Registrazione in corso',\r\n SESSION_RESUME_TEXT: 'C\\'Γ¨ una registrazione attiva non terminata.',\r\n SESSION_RESUME_COUNT: 'comandi catturati',\r\n SESSION_CONTINUE_BTN: 'Continua a registrare',\r\n SESSION_DISCARD_BTN: 'Annulla',\r\n },\r\n};\r\n","export const I18N_DE = {\r\n MAIN_FRAME: {\r\n SETTINGS: 'Einstellungen',\r\n SHOW_ADVANCED_EDITOR: 'Erweiterter Editor',\r\n DIALOG_SAVED_TESTS: 'Gespeicherte Tests',\r\n DIALOG_COMMANDS: 'Cypress-Befehle Vorschau',\r\n DIALOG_SAVE: 'Aufzeichnung speichern?',\r\n },\r\n SAVE_TEST: {\r\n DESC_LABEL: 'Testbeschreibung',\r\n CANCEL: 'Abbrechen',\r\n ASK: 'Aufgezeichneten Test speichern?',\r\n YES_CONTINUE: 'Ja, weiter',\r\n NO_DISCARD: 'Nein, verwerfen',\r\n DESC_PLACEHOLDER: 'Z. B.: Erfolgreiche Anmeldung mit gΓΌltigen Zugangsdaten',\r\n TAGS_LABEL: 'Tags (optional, zum spΓ€teren Filtern):',\r\n TAGS_PLACEHOLDER: 'smoke, login, regressionβ¦',\r\n ADD_TAG: '+ HinzufΓΌgen',\r\n NO_TAGS: 'Keine Tags',\r\n SAVE_BTN: 'πΎ Speichern',\r\n SAVE_AND_EDIT: 'π Speichern und bearbeiten',\r\n REMOVE_TAG_TITLE: 'Entfernen',\r\n NOTES_LABEL: 'Beschreibung / Notizen (optional):',\r\n NOTES_PLACEHOLDER: 'Was dieser Test validiert, Voraussetzungen usw.',\r\n },\r\n TEST_EDITOR: {\r\n NO_TAGS: 'Keine Tags',\r\n SELECTED_SINGULAR: 'ausgewΓ€hlt',\r\n SELECTED_PLURAL: 'ausgewΓ€hlt',\r\n DESCRIBE_PLACEHOLDER: 'describe-Name (optional)',\r\n COPY_DESCRIBE: 'π describe() kopieren',\r\n MULTI_SELECT: 'π Mehrfachauswahl',\r\n CANCEL_SELECT: 'β Abbrechen',\r\n COPY_CMDS_BTN: 'π Befehle kopieren',\r\n COPY_ICPS_BTN: 'π Interceptors kopieren',\r\n DEFAULT_DESCRIBE: 'Test-Suite',\r\n NO_TESTS: 'Keine gespeicherten Tests',\r\n DELETE_TITLE: 'LΓΆschen',\r\n },\r\n CONFIG: {\r\n LANG_SECTION: 'π Sprache',\r\n LANG_FIELD: 'OberflΓ€che',\r\n HTTP_SECTION: 'β‘ Erweitertes HTTP',\r\n HTTP_TITLE: 'Body-Validierungen',\r\n HTTP_SUB: 'GET β Antwort Β· POST/PUT β Anfrage',\r\n SELECTOR_SECTION: 'π― Selector-Strategie',\r\n SELECTOR_LABEL: 'Bevorzugtes Attribut fΓΌr cy.get()',\r\n SELECTOR_OPT_DATACY: 'data-cy (Standard)',\r\n SELECTOR_OPT_TESTID: 'data-testid',\r\n SELECTOR_OPT_ARIA: 'aria-label',\r\n SELECTOR_OPT_ID: 'id (#element)',\r\n SELECTOR_HINT: 'Der Recorder sucht zuerst nach diesem Attribut. Falls nicht gefunden, versucht er die anderen.',\r\n FOLDER_SECTION: 'π Cypress-Ordner',\r\n FOLDER_CONNECTED: 'verbunden β',\r\n FOLDER_NOT_SET: 'nicht konfiguriert',\r\n FOLDER_CHANGE_BTN: 'π Ordner wechseln',\r\n FOLDER_SELECT_BTN: 'π Ordner auswΓ€hlen',\r\n FOLDER_REVOKE_BTN: 'β Zugriff widerrufen',\r\n DATA_SECTION: 'πΎ Daten',\r\n DATA_DESC: 'Exportieren Sie alle Tests als JSON oder importieren Sie ein Backup.',\r\n EXPORT_BTN: 'β¬οΈ Tests exportieren',\r\n EXPORT_DIALOG_TITLE: 'β¬οΈ Tests exportieren',\r\n EXPORT_MODE_ALL: 'Alle',\r\n EXPORT_MODE_MANUAL: 'Manuelle Auswahl',\r\n EXPORT_MODE_TAGS: 'Nach Tags',\r\n EXPORT_ALL_DESC: 'Alle gespeicherten Tests werden exportiert.',\r\n EXPORT_COUNT: 'Zu exportieren:',\r\n EXPORT_CONFIRM: 'β¬οΈ Exportieren',\r\n EXPORT_CANCEL: 'Abbrechen',\r\n EXPORT_EMPTY: 'Keine Tests zum Exportieren.',\r\n EXPORT_NO_TAGS: 'Keine Tags verfΓΌgbar.',\r\n EXPORT_TAGS_HINT: 'WΓ€hle ein oder mehrere Tags, um zu sehen, welche Tests exportiert werden.',\r\n EXPORT_RESULT_LABEL: 'Diese Tests werden exportiert:',\r\n IMPORT_BTN: 'β¬οΈ Tests importieren',\r\n FOLDER_UPDATED_TOAST: 'β Cypress-Ordner aktualisiert',\r\n FOLDER_ERROR_TOAST: 'Fehler beim Zugriff auf den Ordner',\r\n IMPORT_SUCCESS: 'Daten erfolgreich importiert.',\r\n IMPORT_ERROR: 'Fehler beim Importieren.',\r\n JSON_INVALID: 'Die Datei ist kein gΓΌltiges JSON.',\r\n JSON_BAD_FORMAT: 'Die Datei hat nicht das erwartete Format.',\r\n SMART_SELECTOR_SECTION: 'π Intelligenter Selektor',\r\n SMART_SELECTOR_TITLE: 'Intelligenter Selektor',\r\n SMART_SELECTOR_SUB: 'Zeigt ein Auswahlfeld, wenn auf Elemente ohne gΓΌltigen Selektor geklickt wird.',\r\n START_HIDDEN_SECTION: 'π Widget-Sichtbarkeit',\r\n START_HIDDEN_TITLE: 'Versteckt starten',\r\n START_HIDDEN_SUB: 'Das Widget startet unsichtbar. Verwenden Sie Ctrl+Shift+E zum Ein-/Ausblenden.',\r\n RESUME_TTL_SECTION: 'β± AufzeichnungskontinuitΓ€t',\r\n RESUME_TTL_LABEL: 'Ohne Nachfrage fortsetzen (Minuten)',\r\n RESUME_TTL_HINT: 'Wenn Sie neu laden oder das Projekt wechseln, wird eine aktive Aufzeichnung innerhalb dieses Zeitfensters ohne Nachfrage fortgesetzt. Danach werden Sie gefragt, ob fortsetzen oder verwerfen.',\r\n WIDGET_POSITION_SECTION: 'π§² Widget-Position',\r\n WIDGET_POSITION_HINT: 'Ziehe den Aufnahme-Button, um ihn aus dem Weg zu schieben. Die Position wird gespeichert.',\r\n WIDGET_POSITION_RESET_BTN: 'βΊ Position zurΓΌcksetzen',\r\n WIDGET_POSITION_RESET_DONE: 'β Position zurΓΌckgesetzt',\r\n },\r\n SELECTOR_PICKER: {\r\n TITLE: 'DOM-Element auswΓ€hlen',\r\n PREVIEW_LABEL: 'navigieren',\r\n CONFIRM_HINT: 'bestΓ€tigen',\r\n CANCEL_HINT: 'abbrechen',\r\n QUALITY_EXCELLENT: 'Ausgezeichnet β Test-Attribut vorhanden (data-cy / data-testid / aria-label)',\r\n QUALITY_GOOD: 'Gut β gΓΌltige ID',\r\n QUALITY_ACCEPTABLE: 'Akzeptabel β nur CSS-Klassen',\r\n QUALITY_POOR: 'Nicht empfohlen β nur Tag oder Inline-Style',\r\n },\r\n TEST_PREVISUALIZER: {\r\n INTERCEPTORS: 'Interceptors',\r\n COPY_CMDS_BTN: 'π Befehle kopieren',\r\n SHOW_INTERCEPTORS: 'βΌ Interceptors anzeigen',\r\n HIDE_INTERCEPTORS: 'β² Interceptors ausblenden',\r\n SECTION_COMMANDS: 'Befehle',\r\n NO_CMDS_YET: 'Noch keine Befehle',\r\n NO_ICP_SHORT: 'Keine Interceptors',\r\n COPY_ICP_BTN: 'π Interceptors kopieren',\r\n UP_TITLE: 'Nach oben',\r\n DOWN_TITLE: 'Nach unten',\r\n DEL_TITLE: 'LΓΆschen',\r\n },\r\n ADVANCED_EDITOR: {\r\n REAUTH_BTN: 'π Zugriff reaktivieren',\r\n PERMISSION_EXPIRED: 'π Berechtigung abgelaufen',\r\n PERMISSION_EXPIRED_HINT: 'Klicken Sie, um den Zugriff auf Ihren Cypress-Ordner zu reaktivieren.',\r\n NO_ACCESS: 'π Kein Zugriff auf lokale Dateien',\r\n NO_ACCESS_HINT: 'Konfigurieren Sie den Zugriff unter βοΈ Config.',\r\n NO_FILES: 'Keine Dateien',\r\n SELECT_FILE: 'β WΓ€hlen Sie eine Datei aus dem Baum',\r\n IT_LABEL: 'π§ͺ it() zum EinfΓΌgen:',\r\n COPY_IT_BTN: 'π it() kopieren',\r\n BEFORE_EACH_LABEL: 'π beforeEach() Interceptors:',\r\n COPY_ICP_BTN: 'π Interceptors kopieren',\r\n INSERT_BTN: 'πΎ In Datei einfΓΌgen',\r\n EDIT_MANUAL_BTN: 'βοΈ Manuell bearbeiten',\r\n CLOSE_BTN: 'β SchlieΓen',\r\n NEW_FILE_BTN: '+ Neue Datei',\r\n NEW_FOLDER_BTN: '+ Neuer Ordner',\r\n REFRESH_BTN: 'β» Aktualisieren',\r\n NEW_FILE_PLACEHOLDER: 'test-name',\r\n NEW_FOLDER_PLACEHOLDER: 'ordnername',\r\n NEW_FILE_CONFIRM: 'Erstellen',\r\n NEW_FILE_CANCEL: 'Abbrechen',\r\n },\r\n FILE_PREVIEW: {\r\n NO_FILE: 'Keine Datei',\r\n COPY_TITLE: 'Editor-Inhalt kopieren',\r\n BLOCK_IT: 'π§ͺ it()',\r\n COPY_BTN: 'π Kopieren',\r\n BLOCK_BEFORE_EACH: 'π beforeEach()',\r\n NO_CHANGES: 'Keine Γnderungen gegenΓΌber dem Original',\r\n NO_CHANGES_SHORT: 'Keine Γnderungen',\r\n LAUNCH_BTN: 'βΆ Test starten',\r\n LAUNCH_LOCAL_ONLY: 'Wechsle zu localhost, um Tests auszufΓΌhren',\r\n LAUNCH_RUNNING: 'β³ LΓ€uftβ¦',\r\n LAUNCH_PASSED: 'β Test bestanden',\r\n LAUNCH_FAILED: 'β Test fehlgeschlagen',\r\n LAUNCH_NO_RUNNER: 'Kein lokaler Runner erkannt (gestartet?)',\r\n DIFF_BTN: 'π Diff',\r\n SAVE_BTN: 'πΎ Speichern',\r\n CLOSE_BTN: 'β SchlieΓen',\r\n BACK_TO_EDITOR: 'β ZurΓΌck zum Editor',\r\n INSERT_BTN: 'πͺ BlΓΆcke einfΓΌgen',\r\n INSERT_TITLE: 'it() und beforeEach() in den Editor-Inhalt einfΓΌgen',\r\n INSERT_DONE: 'BlΓΆcke in den Editor eingefΓΌgt',\r\n INSERT_ERROR: 'Kein gΓΌltiger describe()-Block in der Datei gefunden',\r\n },\r\n RECORDER: {\r\n FS_TITLE: 'π Dateizugriff',\r\n FS_LATER_BTN: 'Nicht jetzt',\r\n FS_SELECT_BTN: 'π Ordner auswΓ€hlen',\r\n FS_SUCCESS_TOAST: 'β Cypress-Ordner konfiguriert',\r\n FS_ERROR_TOAST: 'Fehler beim Zugriff auf den Ordner',\r\n FS_INTRO_HTML: 'Der <strong style=\"color:#e6edf3\">erweiterte Editor</strong> kann Ihre Tests direkt in die Cypress-Dateien <code style=\"background:#0d1117;padding:1px 6px;border-radius:4px;font-size:11px;color:#c9d1d9\">.cy.ts</code> einfΓΌgen.',\r\n FS_STRUCTURE_HINT_HTML: 'WΓ€hlen Sie den Ordner, der den Unterordner <code style=\"background:#0d1117;padding:1px 5px;border-radius:4px;font-size:10px;color:#c9d1d9\">e2e/</code> enthΓ€lt. Die Erweiterung erwartet diese Struktur:',\r\n FS_TREE_PICK_HINT: 'β diesen Ordner auswΓ€hlen',\r\n FS_TREE_READ_HINT: 'β die Erweiterung liest hier',\r\n FS_PERMISSION_NOTE: 'Die Berechtigung wird im Browser gespeichert und nicht erneut angefordert.',\r\n ASSERTION_SECTION: 'β Assertion hinzufΓΌgen',\r\n ASSERT_SELECTOR_PH: 'Selektor, z. B.: [data-cy=\"btn\"]',\r\n ASSERT_VALUE_PH: 'erwarteter Wert',\r\n ASSERT_ADD_BTN: 'β HinzufΓΌgen',\r\n FILE_EDITOR_TITLE: 'βοΈ Datei-Editor',\r\n FILE_SAVED_TOAST: 'β Datei gespeichert',\r\n FILE_SAVE_ERROR_TOAST: 'Fehler beim Speichern',\r\n BTN_CONFIG: 'Config',\r\n BTN_FILES: 'Dateien',\r\n BTN_COMMANDS: 'Befehle',\r\n BTN_TESTS: 'Tests',\r\n PAUSE_TITLE: 'Pausieren (Ctrl+P)',\r\n RESUME_TITLE: 'Fortsetzen (Ctrl+P)',\r\n BADGE_PAUSED: 'βΈ PAUSE',\r\n BADGE_REC: 'β REC',\r\n STOP_TITLE: 'Stopp (Ctrl+R)',\r\n START_TITLE: 'Aufzeichnen (Ctrl+R)',\r\n SESSION_RESUME_TITLE: 'βΊ Aufzeichnung lΓ€uft',\r\n SESSION_RESUME_TEXT: 'Es gibt eine nicht abgeschlossene aktive Aufzeichnung.',\r\n SESSION_RESUME_COUNT: 'erfasste Befehle',\r\n SESSION_CONTINUE_BTN: 'Weiter aufzeichnen',\r\n SESSION_DISCARD_BTN: 'Verwerfen',\r\n },\r\n};\r\n","import { type Lang, isLang } from '../models/lang.model';\r\nimport { Subject } from '../utils/subject';\r\nimport { I18N_ES } from '../i18n/es';\r\nimport { I18N_EN } from '../i18n/en';\r\nimport { I18N_FR } from '../i18n/fr';\r\nimport { I18N_IT } from '../i18n/it';\r\nimport { I18N_DE } from '../i18n/de';\r\n\r\ntype Translations = typeof I18N_ES;\r\n\r\nexport class TranslationService {\r\n private readonly lang$: Subject<Lang>;\r\n\r\n private readonly translations: Record<Lang, Translations> = {\r\n es: I18N_ES,\r\n en: I18N_EN,\r\n fr: I18N_FR,\r\n it: I18N_IT,\r\n de: I18N_DE,\r\n };\r\n\r\n constructor() {\r\n this.lang$ = new Subject<Lang>(this.detectLang());\r\n }\r\n\r\n setLang(lang: Lang): void {\r\n this.lang$.next(lang);\r\n }\r\n\r\n getLang(): Lang {\r\n return this.lang$.getValue();\r\n }\r\n\r\n /** Subscribe to language changes; returns an unsubscribe function. */\r\n onLangChange(fn: (lang: Lang) => void): () => void {\r\n return this.lang$.subscribe(fn);\r\n }\r\n\r\n translate(key: string): string {\r\n const keys = key.split('.');\r\n let value: unknown = this.translations[this.lang$.getValue()];\r\n for (const k of keys) {\r\n value = (value as Record<string, unknown>)?.[k];\r\n if (value === undefined) return key;\r\n }\r\n return value as string;\r\n }\r\n\r\n detectLang(): Lang {\r\n const browserLang = navigator.language.split('-')[0];\r\n return isLang(browserLang) ? browserLang : 'es';\r\n }\r\n}\r\n\r\nexport const translationService = new TranslationService();\r\n","function gcd(a: number, b: number): number {\n while (b) { const t = b; b = a % b; a = t; }\n return a;\n}\n\n/**\n * Escapes backslashes and single quotes so a value can be safely embedded inside\n * a single-quoted JavaScript string literal β e.g. an `it('β¦')` / `describe('β¦')`\n * name. Without this, a test named `User's login` produces broken generated JS.\n */\nexport function escapeSingleQuotes(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\n/**\n * Normalizes indentation in a code block and prefixes every line with baseIndent.\n *\n * Algorithm:\n * 1. Strip trailing whitespace from each line.\n * 2. Find the minimum leading-whitespace count of non-empty lines (dedent).\n * 3. Compute the indent step as the GCD of all non-zero relative indent values,\n * so the original indent unit (4-space, 8-space, etc.) maps to 2-space levels.\n * 4. Re-emit each line as: baseIndent + ' '.repeat(level) + trimmedContent.\n *\n * This handles multi-line interceptor/command blocks that were stored with\n * inconsistent or file-origin indentation.\n */\nexport function normalizeBlock(code: string, baseIndent: string): string {\n const lines = code.split('\\n').map(l => l.trimEnd());\n const nonEmpty = lines.filter(l => l.trim().length > 0);\n if (!nonEmpty.length) return '';\n\n const indents = nonEmpty.map(l => l.length - l.trimStart().length);\n const minIndent = Math.min(...indents);\n const relIndents = [...new Set(indents.map(n => n - minIndent).filter(n => n > 0))];\n const step = relIndents.length > 0 ? relIndents.reduce(gcd) : 2;\n\n return lines\n .map(l => {\n if (!l.trim()) return '';\n const level = Math.round((l.length - l.trimStart().length - minIndent) / step);\n return baseIndent + ' '.repeat(level) + l.trimStart();\n })\n .join('\\n');\n}\n","import { type Lang, isLang } from '../models/lang.model';\r\nimport { normalizeBlock, escapeSingleQuotes } from '../utils/code-format.utils';\r\n\r\nexport class TransformationService {\r\n toLang(lang: string): Lang {\r\n return isLang(lang) ? lang : 'en';\r\n }\r\n\r\n generateItDescription(description: string, commands: string[]): string {\r\n const commandsBlock = commands.map((cmd) => normalizeBlock(cmd, ' ')).join('\\n');\r\n return `it('${escapeSingleQuotes(description)}', () => {\\n${commandsBlock}\\n});`;\r\n }\r\n}\r\n\r\nexport const transformationService = new TransformationService();\r\n","export interface DirectoryNode {\r\n name: string;\r\n kind: 'directory';\r\n children: (DirectoryNode | FileNode)[];\r\n}\r\n\r\nexport interface FileNode {\r\n name: string;\r\n kind: 'file';\r\n}\r\n\r\nexport class AdvancedTestTransformationService {\r\n insertBeforeEach(content: string, interceptors: string, alertFn?: (msg: string) => void): string {\r\n const match = content.match(/(describe\\s*\\(.*?{)/s);\r\n if (!match) {\r\n alertFn?.('ADVANCED_EDITOR.NO_DESCRIBE');\r\n return '';\r\n }\r\n const insertPos = (match.index ?? 0) + match[0].length;\r\n const beforeEachBlock = `\\n beforeEach(() => {\\n${interceptors} })\\n`;\r\n return content.slice(0, insertPos) + beforeEachBlock + content.slice(insertPos);\r\n }\r\n\r\n insertItBlock(content: string, itBlock: string, alertFn?: (msg: string) => void): string {\r\n const idx = content.lastIndexOf('})');\r\n if (idx === -1) {\r\n alertFn?.('ADVANCED_EDITOR.NO_END');\r\n return '';\r\n }\r\n return content.slice(0, idx) + '\\n' + itBlock + '\\n' + content.slice(idx);\r\n }\r\n\r\n buildBlockComment(notes: string): string {\r\n if (!notes.trim()) return '';\r\n const lines = notes.split('\\n').map(l => ` * ${l}`).join('\\n');\r\n return `/**\\n${lines}\\n */`;\r\n }\r\n\r\n isFile(file: unknown): boolean {\r\n return !!file && (file as FileNode).kind === 'file';\r\n }\r\n\r\n async scanDirectory(dirHandle: FileSystemDirectoryHandle): Promise<DirectoryNode> {\r\n const result: DirectoryNode = { name: dirHandle.name, kind: 'directory', children: [] };\r\n for await (const entry of dirHandle.values()) {\r\n if (entry.kind === 'directory') {\r\n result.children.push(await this.scanDirectory(entry as FileSystemDirectoryHandle));\r\n } else {\r\n result.children.push({ name: entry.name, kind: 'file' });\r\n }\r\n }\r\n return result;\r\n }\r\n}\r\n\r\nexport const advancedTestTransformationService = new AdvancedTestTransformationService();\r\n","import { INPUT_TYPES } from '../models/input-types.model';\r\nimport type { ActiveSessionState } from '../models/active-session.model';\r\nimport { Subject } from '../utils/subject';\r\nimport { FORBIDDEN_ID_PREFIXES } from '../utils/selector-quality.utils';\r\n\r\nconst OWN_SELECTOR = '[data-cy=\"lib-e2e-cypress-for-dummys\"]';\r\n\r\nexport type SelectorStrategy = 'data-cy' | 'data-testid' | 'aria-label' | 'id';\r\n\r\n/** Generates a stable, collision-resistant session id (browser + jsdom safe). */\r\nfunction createSessionId(): string {\r\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\r\n return crypto.randomUUID();\r\n }\r\n return `sess-${Date.now().toString(36)}-${Math.floor(Math.random() * 1e9).toString(36)}`;\r\n}\r\n\r\nexport class RecordingService {\r\n private readonly commands$ = new Subject<string[]>([]);\r\n private readonly interceptors$ = new Subject<string[]>([]);\r\n private readonly isRecording$ = new Subject<boolean>(false);\r\n private readonly isPaused$ = new Subject<boolean>(false);\r\n private readonly selectorNotFound$ = new Subject<{ target: HTMLElement; action: 'click' } | null>(null);\r\n private readonly inputDebounceTimers = new Map<HTMLElement, ReturnType<typeof setTimeout>>();\r\n private readonly abort = new AbortController();\r\n\r\n selectorStrategy: SelectorStrategy = 'data-cy';\r\n\r\n /** Stable id of the current live session (null when none has started). */\r\n sessionId: string | null = null;\r\n private startedAt = 0;\r\n\r\n // Stored originals for history patching cleanup\r\n private readonly origPushState = history.pushState.bind(history);\r\n private readonly origReplaceState = history.replaceState.bind(history);\r\n\r\n constructor() {\r\n this.listenToClicks();\r\n this.listenToInput();\r\n this.listenToSelect();\r\n this.listenToRouteChanges();\r\n }\r\n\r\n // ββ Public API ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n startRecording(): void {\r\n this.sessionId = createSessionId();\r\n this.startedAt = Date.now();\r\n this.isPaused$.next(false);\r\n this.isRecording$.next(true);\r\n this.addCommand(`cy.viewport(1900, 1200)`);\r\n this.addCommand(`cy.visit('${window.location.pathname}')`);\r\n this.addCommand(`cy.get('[data-cy=\"lib-e2e-cypress-for-dummys\"]').invoke('hide');`);\r\n }\r\n\r\n /**\r\n * Rehydrates a previously persisted session WITHOUT running the startRecording\r\n * bootstrap (no viewport/visit/hide). Used to continue a recording across a\r\n * micro-frontend crossing or a same-origin reload.\r\n * See docs/specs/006-cross-app-recording-continuity.md.\r\n */\r\n restoreSession(state: ActiveSessionState): void {\r\n this.sessionId = state.sessionId;\r\n this.startedAt = state.startedAt;\r\n this.selectorStrategy = state.selectorStrategy;\r\n this.commands$.next([...state.commands]);\r\n this.interceptors$.next([...state.interceptors]);\r\n this.isPaused$.next(state.isPaused);\r\n // isRecording last so subscribers observe a fully-populated buffer.\r\n this.isRecording$.next(state.isRecording);\r\n }\r\n\r\n /** Full snapshot of the live session for persistence. */\r\n getSessionSnapshot(): ActiveSessionState {\r\n return {\r\n sessionId: this.sessionId ?? createSessionId(),\r\n isRecording: this.isRecording$.getValue(),\r\n isPaused: this.isPaused$.getValue(),\r\n commands: this.commands$.getValue(),\r\n interceptors: this.interceptors$.getValue(),\r\n selectorStrategy: this.selectorStrategy,\r\n startedAt: this.startedAt,\r\n updatedAt: Date.now(),\r\n };\r\n }\r\n\r\n stopRecording(): void {\r\n this.isPaused$.next(false);\r\n this.isRecording$.next(false);\r\n }\r\n\r\n toggleRecording(): void {\r\n if (this.isRecording$.getValue()) {\r\n this.stopRecording();\r\n } else {\r\n this.startRecording();\r\n }\r\n }\r\n\r\n pauseRecording(): void {\r\n if (!this.isRecording$.getValue()) return;\r\n this.isPaused$.next(true);\r\n }\r\n\r\n resumeRecording(): void {\r\n this.isPaused$.next(false);\r\n }\r\n\r\n togglePause(): void {\r\n if (this.isPaused$.getValue()) {\r\n this.resumeRecording();\r\n } else {\r\n this.pauseRecording();\r\n }\r\n }\r\n\r\n addCommand(cmd: string): void {\r\n if (!this.isRecording$.getValue() || this.isPaused$.getValue()) return;\r\n this.commands$.next([...this.commands$.getValue(), cmd]);\r\n }\r\n\r\n /** Appends a command regardless of recording/paused state (e.g. assertions added manually). */\r\n appendCommand(cmd: string): void {\r\n this.commands$.next([...this.commands$.getValue(), cmd]);\r\n }\r\n\r\n removeCommand(index: number): void {\r\n const cmds = this.commands$.getValue();\r\n if (index < 0 || index >= cmds.length) return;\r\n this.commands$.next([...cmds.slice(0, index), ...cmds.slice(index + 1)]);\r\n }\r\n\r\n moveCommand(from: number, to: number): void {\r\n const cmds = [...this.commands$.getValue()];\r\n if (from < 0 || to < 0 || from >= cmds.length || to >= cmds.length || from === to) return;\r\n const [item] = cmds.splice(from, 1);\r\n cmds.splice(to, 0, item);\r\n this.commands$.next(cmds);\r\n }\r\n\r\n removeInterceptor(index: number): void {\r\n const ints = this.interceptors$.getValue();\r\n if (index < 0 || index >= ints.length) return;\r\n this.interceptors$.next([...ints.slice(0, index), ...ints.slice(index + 1)]);\r\n }\r\n\r\n registerInterceptor(method: string, url: string, alias: string): void {\r\n if (this.isPaused$.getValue()) return;\r\n const command = `cy.intercept('${method}', '${this.urlToWildcard(url, method)}').as('${alias}')`;\r\n const current = this.interceptors$.getValue();\r\n if (!current.includes(command)) {\r\n this.interceptors$.next([...current, command]);\r\n }\r\n }\r\n\r\n clearCommands(): void {\r\n this.commands$.next([]);\r\n this.interceptors$.next([]);\r\n }\r\n\r\n clearInterceptors(): void {\r\n this.interceptors$.next([]);\r\n }\r\n\r\n getCommandsSnapshot(): string[] { return this.commands$.getValue(); }\r\n getInterceptorsSnapshot(): string[] { return this.interceptors$.getValue(); }\r\n getPausedSnapshot(): boolean { return this.isPaused$.getValue(); }\r\n\r\n onCommandsChange(fn: (cmds: string[]) => void): () => void {\r\n return this.commands$.subscribe(fn);\r\n }\r\n\r\n onInterceptorsChange(fn: (ints: string[]) => void): () => void {\r\n return this.interceptors$.subscribe(fn);\r\n }\r\n\r\n onRecordingChange(fn: (isRecording: boolean) => void): () => void {\r\n return this.isRecording$.subscribe(fn);\r\n }\r\n\r\n onPauseChange(fn: (isPaused: boolean) => void): () => void {\r\n return this.isPaused$.subscribe(fn);\r\n }\r\n\r\n /**\r\n * Fires a full session snapshot whenever any persisted field changes\r\n * (commands, interceptors, recording or paused state). Drives the debounced\r\n * persistence of the live session. Returns a combined unsubscribe.\r\n */\r\n onSessionChange(fn: (state: ActiveSessionState) => void): () => void {\r\n const emit = (): void => fn(this.getSessionSnapshot());\r\n const unsubs = [\r\n this.commands$.subscribe(emit),\r\n this.interceptors$.subscribe(emit),\r\n this.isRecording$.subscribe(emit),\r\n this.isPaused$.subscribe(emit),\r\n ];\r\n return () => unsubs.forEach((u) => u());\r\n }\r\n\r\n onSelectorNotFound(fn: (target: HTMLElement, action: 'click') => void): () => void {\r\n return this.selectorNotFound$.subscribe((v) => {\r\n if (v) fn(v.target, v.action);\r\n });\r\n }\r\n\r\n destroy(): void {\r\n this.abort.abort();\r\n history.pushState = this.origPushState;\r\n history.replaceState = this.origReplaceState;\r\n this.inputDebounceTimers.forEach((t) => clearTimeout(t));\r\n this.inputDebounceTimers.clear();\r\n }\r\n\r\n // ββ DOM listeners βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private listenToClicks(): void {\r\n document.addEventListener(\r\n 'click',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n const tag = target.tagName?.toLowerCase();\r\n if (tag === 'body' || tag === 'html') return;\r\n this.handleClickEvent(target);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToInput(): void {\r\n document.addEventListener(\r\n 'input',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLInputElement | HTMLTextAreaElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n this.handleInputEvent(target);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToSelect(): void {\r\n document.addEventListener(\r\n 'change',\r\n (e: Event) => {\r\n if (!this.isRecording$.getValue()) return;\r\n const target = e.target as HTMLSelectElement;\r\n if (!target || this.isOwnElement(target)) return;\r\n if (target.tagName.toLowerCase() === 'select') {\r\n this.handleSelectEvent(target);\r\n }\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n private listenToRouteChanges(): void {\r\n let lastUrl = window.location.pathname + window.location.search + window.location.hash;\r\n\r\n const addUrlCommand = (newUrl: string): void => {\r\n if (!this.isRecording$.getValue()) return;\r\n if (newUrl === lastUrl) return;\r\n this.addCommand(`cy.url().should('include', '${newUrl}')`);\r\n lastUrl = newUrl;\r\n };\r\n\r\n const wrapMethod = (type: 'pushState' | 'replaceState'): void => {\r\n const orig = history[type].bind(history);\r\n history[type] = (data: unknown, unused: string, url?: string | URL | null) => {\r\n const result = orig(data, unused, url);\r\n let newUrl = window.location.pathname + window.location.search + window.location.hash;\r\n if (typeof url === 'string' && url.length > 0) {\r\n const a = document.createElement('a');\r\n a.href = url;\r\n newUrl = a.pathname + a.search + a.hash;\r\n } else if (url instanceof URL) {\r\n newUrl = url.pathname + url.search + url.hash;\r\n }\r\n addUrlCommand(newUrl);\r\n return result;\r\n };\r\n };\r\n\r\n wrapMethod('pushState');\r\n wrapMethod('replaceState');\r\n\r\n window.addEventListener(\r\n 'popstate',\r\n () => {\r\n const newUrl = window.location.pathname + window.location.search + window.location.hash;\r\n addUrlCommand(newUrl);\r\n },\r\n { signal: this.abort.signal }\r\n );\r\n }\r\n\r\n // ββ Click helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleClickEvent(target: HTMLElement): void {\r\n // Bubble up from non-interactive span/div inside button or mat-option\r\n if (!this.isInteractiveElement(target)) {\r\n const tag = target.tagName.toLowerCase();\r\n if (\r\n (tag === 'span' || tag === 'div') &&\r\n target.parentElement &&\r\n (target.parentElement.tagName.toLowerCase() === 'button' ||\r\n target.parentElement.tagName.toLowerCase() === 'mat-option') &&\r\n (target.parentElement.hasAttribute('data-cy') || target.parentElement.hasAttribute('id'))\r\n ) {\r\n target = target.parentElement;\r\n }\r\n const matSelect = target.closest('mat-select');\r\n if (matSelect) {\r\n const sel = this.getReliableSelector(matSelect as HTMLElement);\r\n if (sel) {\r\n this.addCommand(`cy.get('${sel}').click()`);\r\n } else {\r\n this.selectorNotFound$.next({ target: matSelect as HTMLElement, action: 'click' });\r\n }\r\n return;\r\n }\r\n }\r\n\r\n const tag = target.tagName.toLowerCase();\r\n if (tag === 'input' || tag === 'textarea' || tag === 'select') {\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) this.selectorNotFound$.next({ target, action: 'click' });\r\n return;\r\n }\r\n\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) {\r\n this.selectorNotFound$.next({ target, action: 'click' });\r\n return;\r\n }\r\n\r\n const selector = this.getReliableSelector(container);\r\n if (selector === OWN_SELECTOR) return;\r\n\r\n if (tag === 'mat-option') {\r\n this.handleMatOptionClick(target, selector);\r\n return;\r\n }\r\n\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').click()`,\r\n });\r\n }\r\n\r\n private handleMatOptionClick(target: HTMLElement, selector: string | null): void {\r\n const matSelect = target.closest('mat-select');\r\n let dataCy: string | null = null;\r\n if (matSelect) dataCy = matSelect.closest('[data-cy]')?.getAttribute('data-cy') ?? null;\r\n if (!dataCy) dataCy = target.closest('[data-cy]')?.getAttribute('data-cy') ?? null;\r\n if (dataCy) {\r\n this.addCommand(`cy.get('[data-cy=\"${dataCy}\"]').click()`);\r\n return;\r\n }\r\n if (selector) {\r\n this.addCommand(`cy.get('${selector}').eq(0).click()`);\r\n } else {\r\n this.selectorNotFound$.next({ target, action: 'click' });\r\n }\r\n }\r\n\r\n // ββ Input helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleInputEvent(target: HTMLInputElement | HTMLTextAreaElement): void {\r\n const tag = target.tagName.toLowerCase();\r\n const isText = tag === 'textarea' || (tag === 'input' && (INPUT_TYPES as readonly string[]).includes(target.type));\r\n if (!isText) return;\r\n\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) return;\r\n\r\n if (this.inputDebounceTimers.has(target)) {\r\n clearTimeout(this.inputDebounceTimers.get(target));\r\n }\r\n this.inputDebounceTimers.set(\r\n target,\r\n setTimeout(() => {\r\n const selector = this.getReliableSelector(container);\r\n const value = target.value.replace(/'/g, \"\\\\'\");\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').clear().type('${value}')`,\r\n });\r\n this.inputDebounceTimers.delete(target);\r\n }, 1000)\r\n );\r\n }\r\n\r\n // ββ Select helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private handleSelectEvent(target: HTMLSelectElement): void {\r\n const container = target.closest<HTMLElement>('[data-cy], [data-testid], [aria-label], [id]');\r\n if (!container) return;\r\n const selector = this.getReliableSelector(container);\r\n const value = target.value.replace(/'/g, \"\\\\'\");\r\n this.addGenericCommand({\r\n selector,\r\n action: (s) => `cy.get('${s}').select('${value}')`,\r\n });\r\n }\r\n\r\n // ββ Shared helpers ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private addGenericCommand(opts: {\r\n selector: string | null;\r\n action: (s: string) => string;\r\n }): void {\r\n if (!opts.selector || this.isOwnSelector(opts.selector)) return;\r\n this.addCommand(opts.action(opts.selector));\r\n }\r\n\r\n private getReliableSelector(el: HTMLElement): string | null {\r\n const strategy = this.selectorStrategy;\r\n const dataCy = el.getAttribute('data-cy');\r\n const dataTestid = el.getAttribute('data-testid');\r\n const ariaLabel = el.getAttribute('aria-label');\r\n const dataDotCy = el.getAttribute('data.cy');\r\n\r\n const rawId = el.id;\r\n const validId = rawId &&\r\n rawId.length < 25 &&\r\n /^[a-zA-Z][\\w-]*$/.test(rawId) &&\r\n !FORBIDDEN_ID_PREFIXES.some((p) => rawId.startsWith(p)) &&\r\n !/^\\d+$/.test(rawId) ? rawId : null;\r\n\r\n switch (strategy) {\r\n case 'data-testid':\r\n if (dataTestid) return `[data-testid=\"${dataTestid}\"]`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n case 'aria-label':\r\n if (ariaLabel) return `[aria-label=\"${ariaLabel}\"]`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n case 'id':\r\n if (validId) return `#${validId}`;\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n return dataTestid ? `[data-testid=\"${dataTestid}\"]` : null;\r\n default: // 'data-cy'\r\n if (dataCy) return `[data-cy=\"${dataCy}\"]`;\r\n if (dataDotCy) return `[data.cy=\"${dataDotCy}\"]`;\r\n return validId ? `#${validId}` : null;\r\n }\r\n }\r\n\r\n private isInteractiveElement(target: EventTarget | null): boolean {\r\n if (!(target instanceof HTMLElement)) return false;\r\n const tag = target.tagName.toLowerCase();\r\n return ['select', 'option', 'input', 'textarea', 'button'].includes(tag);\r\n }\r\n\r\n private isOwnSelector(selector: string | null): boolean {\r\n return selector === OWN_SELECTOR;\r\n }\r\n\r\n private isOwnElement(target: HTMLElement): boolean {\r\n return !!target.closest('[data-cy=\"lib-e2e-cypress-for-dummys\"]');\r\n }\r\n\r\n private urlToWildcard(url: string, method: string): string {\r\n const u = new URL(url, 'http://localhost');\r\n if (method.toUpperCase() === 'GET' && u.search) {\r\n return `**${u.pathname}/**`;\r\n }\r\n return `**${u.pathname}`;\r\n }\r\n}\r\n","import { openDB, type IDBPDatabase } from 'idb';\r\nimport { DB_SCHEMA } from '../models/db-schema.model';\r\nimport type { ActiveSessionState } from '../models/active-session.model';\r\nimport { normalizeBlock, escapeSingleQuotes } from '../utils/code-format.utils';\r\n\r\n/** Fixed primary key for the single active-session record. */\r\nconst ACTIVE_SESSION_ID = 1;\r\n\r\ninterface TestRecord { id: number; name: string; createdAt: number; tags?: string[]; notes?: string; }\r\ninterface CommandRecord { id: number; command: string; testId: number; createdAt: number; }\r\ninterface InterceptorRecord { id: number; interceptor: string; testId: number; createdAt: number; }\r\ninterface ConfigRecord { id: number; [key: string]: unknown; }\r\n\r\nexport interface TestWithDetails extends TestRecord {\r\n commands: string[];\r\n interceptors: string[];\r\n}\r\n\r\nexport interface TestDetail extends TestWithDetails {\r\n cypressCommands: string[];\r\n itBlock: string;\r\n interceptorsBlock: string;\r\n}\r\n\r\nexport class PersistenceService {\r\n private _db: Promise<IDBPDatabase> | null = null;\r\n\r\n // dbName is overridable so tests can use unique names for isolation.\r\n constructor(private readonly dbName: string = DB_SCHEMA.name) {}\r\n\r\n private getDB(): Promise<IDBPDatabase> {\r\n if (!this._db) {\r\n this._db = openDB(this.dbName, DB_SCHEMA.version, {\r\n upgrade(database) {\r\n for (const store of DB_SCHEMA.stores) {\r\n if (!database.objectStoreNames.contains(store.name)) {\r\n const os = database.createObjectStore(store.name, {\r\n keyPath: store.keyPath,\r\n autoIncrement: store.autoIncrement,\r\n });\r\n for (const index of store.indexes) {\r\n os.createIndex(index.name, index.keyPath, { unique: index.unique });\r\n }\r\n }\r\n }\r\n },\r\n });\r\n }\r\n return this._db;\r\n }\r\n\r\n // ββ Tests βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertTest(name: string, commands: string[] = [], interceptors: string[] = [], tags: string[] = [], notes?: string): Promise<number> {\r\n const db = await this.getDB();\r\n const record: Omit<TestRecord, 'id'> = { name, createdAt: Date.now(), ...(tags.length ? { tags } : {}), ...(notes ? { notes } : {}) };\r\n const id = await db.add('tests', record) as number;\r\n if (commands.length) await this.insertCommands(commands, id);\r\n if (interceptors.length) await this.insertInterceptors(interceptors, id);\r\n return id;\r\n }\r\n\r\n async getAllTests(): Promise<TestWithDetails[]> {\r\n const db = await this.getDB();\r\n const tests = await db.getAll('tests') as TestRecord[];\r\n return Promise.all(\r\n tests.map(async (test) => ({\r\n ...test,\r\n commands: await this.getCommandStrings(test.id),\r\n interceptors: await this.getInterceptorStrings(test.id),\r\n }))\r\n );\r\n }\r\n\r\n async getTestById(testId: number): Promise<TestDetail | null> {\r\n const db = await this.getDB();\r\n const record = await db.get('tests', testId) as TestRecord | undefined;\r\n if (!record) return null;\r\n\r\n const commands = await this.getCommandStrings(testId);\r\n const interceptors = await this.getInterceptorStrings(testId);\r\n const itBlock = `it('${escapeSingleQuotes(record.name)}', () => {\\n${commands.map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});`;\r\n const interceptorsBlock = interceptors.length\r\n ? ' // Auto-generated Cypress interceptors\\n' +\r\n interceptors.map(i => normalizeBlock(i, ' ')).join('\\n') + '\\n'\r\n : '';\r\n\r\n return { ...record, commands, interceptors, cypressCommands: commands, itBlock, interceptorsBlock };\r\n }\r\n\r\n async deleteTest(id: number): Promise<void> {\r\n const db = await this.getDB();\r\n await db.delete('tests', id);\r\n await this.deleteCommandsByTestId(id);\r\n await this.deleteInterceptorsByTestId(id);\r\n }\r\n\r\n // ββ Commands ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertCommands(commands: string[], testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all(\r\n commands.map((command) => db.add('commands', { command, testId, createdAt: Date.now() }))\r\n );\r\n }\r\n\r\n async getCommandsByTestId(testId: number): Promise<CommandRecord[]> {\r\n const db = await this.getDB();\r\n return db.getAllFromIndex('commands', 'testId', testId) as Promise<CommandRecord[]>;\r\n }\r\n\r\n private async getCommandStrings(testId: number): Promise<string[]> {\r\n return (await this.getCommandsByTestId(testId)).map((r) => r.command).filter(Boolean);\r\n }\r\n\r\n private async deleteCommandsByTestId(testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n const rows = await this.getCommandsByTestId(testId);\r\n const tx = db.transaction('commands', 'readwrite');\r\n await Promise.all(rows.map((r) => tx.store.delete(r.id)));\r\n await tx.done;\r\n }\r\n\r\n // ββ Interceptors ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async insertInterceptors(interceptors: string[], testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all(\r\n interceptors.map((interceptor) => db.add('interceptors', { interceptor, testId, createdAt: Date.now() }))\r\n );\r\n }\r\n\r\n async getInterceptorsByTestId(testId: number): Promise<InterceptorRecord[]> {\r\n const db = await this.getDB();\r\n return db.getAllFromIndex('interceptors', 'testId', testId) as Promise<InterceptorRecord[]>;\r\n }\r\n\r\n private async getInterceptorStrings(testId: number): Promise<string[]> {\r\n return (await this.getInterceptorsByTestId(testId)).map((r) => r.interceptor).filter(Boolean);\r\n }\r\n\r\n async deleteInterceptorsByTestId(testId: number): Promise<void> {\r\n const db = await this.getDB();\r\n const rows = await this.getInterceptorsByTestId(testId);\r\n const tx = db.transaction('interceptors', 'readwrite');\r\n await Promise.all(rows.map((r) => tx.store.delete(r.id)));\r\n await tx.done;\r\n }\r\n\r\n // ββ Configuration βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async setConfig(config: Record<string, unknown>): Promise<void> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n const current = records[0] ?? {};\r\n const merged = { ...current, ...config };\r\n if ((current as ConfigRecord).id) {\r\n await db.put('configuration', merged);\r\n } else {\r\n await db.add('configuration', merged);\r\n }\r\n }\r\n\r\n async setConfigKey(key: string, value: unknown): Promise<void> {\r\n return this.setConfig({ [key]: value });\r\n }\r\n\r\n async getConfig(key: string): Promise<Record<string, unknown> | null> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n if (!records.length) return null;\r\n const config = records[0];\r\n return Object.prototype.hasOwnProperty.call(config, key) ? { [key]: config[key] } : null;\r\n }\r\n\r\n async getGeneralConfig(): Promise<ConfigRecord | null> {\r\n const db = await this.getDB();\r\n const records = await db.getAll('configuration') as ConfigRecord[];\r\n return records[0] ?? null;\r\n }\r\n\r\n // ββ Active recording session ββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n /** Upserts the live recording session (single record, fixed key). */\r\n async saveActiveSession(state: ActiveSessionState): Promise<void> {\r\n const db = await this.getDB();\r\n await db.put('activeSession', { ...state, id: ACTIVE_SESSION_ID });\r\n }\r\n\r\n /** Returns the persisted live session, or null when none is stored. */\r\n async getActiveSession(): Promise<ActiveSessionState | null> {\r\n const db = await this.getDB();\r\n const record = await db.get('activeSession', ACTIVE_SESSION_ID) as (ActiveSessionState & { id: number }) | undefined;\r\n if (!record) return null;\r\n const { id: _id, ...state } = record;\r\n return state as ActiveSessionState;\r\n }\r\n\r\n /** Removes the live session record. Safe to call when none exists. */\r\n async clearActiveSession(): Promise<void> {\r\n const db = await this.getDB();\r\n await db.delete('activeSession', ACTIVE_SESSION_ID);\r\n }\r\n\r\n // ββ Bulk operations βββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n async clearAllData(): Promise<void> {\r\n const db = await this.getDB();\r\n await Promise.all([\r\n db.clear('tests'),\r\n db.clear('commands'),\r\n db.clear('interceptors'),\r\n ]);\r\n }\r\n\r\n async ingestFileData(tests: Record<string, unknown>[], interceptors: Record<string, unknown>[]): Promise<void> {\r\n if (Array.isArray(tests)) {\r\n const db = await this.getDB();\r\n for (const test of tests) {\r\n // Split the nested commands/interceptors back into their own stores,\r\n // keyed by the freshly-assigned testId β otherwise they would be stored\r\n // as stray fields and silently lost on read (getAllTests reads them by\r\n // testId from the commands/interceptors stores).\r\n const { id: _id, commands, interceptors: testInterceptors, ...record } = test;\r\n const newId = await db.add('tests', record) as number;\r\n const cmds = Array.isArray(commands) ? commands as string[] : [];\r\n const icps = Array.isArray(testInterceptors) ? testInterceptors as string[] : [];\r\n if (cmds.length) await this.insertCommands(cmds, newId);\r\n if (icps.length) await this.insertInterceptors(icps, newId);\r\n }\r\n }\r\n // Back-compat: legacy files may carry top-level interceptors with their own testId.\r\n await this.bulkInsertWithoutId('interceptors', interceptors);\r\n }\r\n\r\n async requestDirectoryPermissions(): Promise<void> {\r\n if (!('showDirectoryPicker' in window)) {\r\n throw new Error('File System Access API not supported');\r\n }\r\n const dirHandle = await window.showDirectoryPicker();\r\n await this.setConfigKey('cypressDirectoryHandle', dirHandle);\r\n await this.setConfigKey('allowReadWriteFiles', 'true');\r\n }\r\n\r\n private async bulkInsertWithoutId(store: string, items: Record<string, unknown>[]): Promise<void> {\r\n if (!Array.isArray(items)) return;\r\n const db = await this.getDB();\r\n for (const item of items) {\r\n const { id: _id, ...rest } = item;\r\n await db.add(store, rest);\r\n }\r\n }\r\n}\r\n\r\nexport const persistenceService = new PersistenceService();\r\n","import { type RecordingService } from './recording.service';\r\n\r\nconst INTERCEPTED_METHODS = ['GET', 'POST', 'PUT'] as const;\r\ntype InterceptedMethod = (typeof INTERCEPTED_METHODS)[number];\r\n\r\nexport function generateAlias(method: string, url: string): string {\r\n try {\r\n const u = new URL(url, 'http://localhost');\r\n const path = u.pathname\r\n .replace(/[^a-zA-Z0-9]/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/(^-)|(-$)/g, '');\r\n return `${method.toLowerCase()}-${path}`;\r\n } catch {\r\n return `${method.toLowerCase()}-intercepted-request`;\r\n }\r\n}\r\n\r\nfunction buildValidations(base: string, obj: Record<string, unknown>): string {\r\n return Object.keys(obj)\r\n .filter((key) => key !== 'id' && key !== 'uid')\r\n .map((key) => `expect(${base}.${key}).to.equal(${JSON.stringify(obj[key])});`)\r\n .join('\\n');\r\n}\r\n\r\nfunction buildCyWaitCommand(\r\n method: string,\r\n alias: string,\r\n extendedHttp: boolean,\r\n requestBody: Record<string, unknown> | null,\r\n responseBody: Record<string, unknown> | null\r\n): string {\r\n if (extendedHttp && method === 'GET' && responseBody) {\r\n const validations = buildValidations('interception.response.body', responseBody);\r\n return `cy.wait('@${alias}').then((interception) => {\\n if (interception.response) {\\n${validations}\\n }\\n})`;\r\n }\r\n if (extendedHttp && (method === 'POST' || method === 'PUT') && requestBody) {\r\n const validations = buildValidations('interception.request.body', requestBody);\r\n return `cy.wait('@${alias}').then((interception) => {\\n${validations}\\n})`;\r\n }\r\n return `cy.wait('@${alias}').then((interception) => { })`;\r\n}\r\n\r\nfunction parseJsonObject(text: string): Record<string, unknown> | null {\r\n try {\r\n const parsed = JSON.parse(text);\r\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\r\n return parsed as Record<string, unknown>;\r\n }\r\n } catch {\r\n // Non-JSON or array β fall through\r\n }\r\n return null;\r\n}\r\n\r\nfunction parseRequestBody(init?: RequestInit): Record<string, unknown> | null {\r\n const body = init?.body;\r\n if (typeof body === 'string') return parseJsonObject(body);\r\n return null;\r\n}\r\n\r\nfunction resolveUrl(input: RequestInfo | URL): string {\r\n if (typeof input === 'string') return input;\r\n if (input instanceof URL) return input.href;\r\n return input.url;\r\n}\r\n\r\nfunction resolveMethod(input: RequestInfo | URL, init?: RequestInit): string {\r\n if (init?.method) return init.method.toUpperCase();\r\n if (input instanceof Request) return input.method.toUpperCase();\r\n return 'GET';\r\n}\r\n\r\nexport class HttpMonitor {\r\n private originalFetch: typeof window.fetch | null = null;\r\n private originalXHR: typeof XMLHttpRequest | null = null;\r\n\r\n constructor(private readonly recording: RecordingService) {}\r\n\r\n install(): void {\r\n this.installFetch();\r\n this.installXhr();\r\n }\r\n\r\n uninstall(): void {\r\n this.uninstallFetch();\r\n this.uninstallXhr();\r\n }\r\n\r\n isExtendedHttpEnabled(): boolean {\r\n return localStorage.getItem('extendedHttpCommands') === 'true';\r\n }\r\n\r\n private installFetch(): void {\r\n if (this.originalFetch) return;\r\n const originalFetch = window.fetch;\r\n this.originalFetch = originalFetch;\r\n\r\n window.fetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\r\n const response = await originalFetch(input, init);\r\n try {\r\n await this.handleFetchInterception(input, init, response.clone());\r\n } catch {\r\n // Never let monitoring errors break the actual request\r\n }\r\n return response;\r\n };\r\n }\r\n\r\n private uninstallFetch(): void {\r\n if (!this.originalFetch) return;\r\n window.fetch = this.originalFetch;\r\n this.originalFetch = null;\r\n }\r\n\r\n private installXhr(): void {\r\n if (this.originalXHR) return;\r\n this.originalXHR = window.XMLHttpRequest;\r\n const OrigXHR = this.originalXHR;\r\n const handleXhrInterception = this.handleXhrInterception.bind(this);\r\n\r\n window.XMLHttpRequest = class extends OrigXHR {\r\n private _xhrMethod = 'GET';\r\n private _xhrUrl = '';\r\n private _xhrRequestBody: Record<string, unknown> | null = null;\r\n\r\n override open(\r\n method: string,\r\n url: string | URL,\r\n async = true,\r\n user?: string | null,\r\n password?: string | null\r\n ): void {\r\n this._xhrMethod = method.toUpperCase();\r\n this._xhrUrl = url instanceof URL ? url.href : url;\r\n super.open(method, url as string, async, user, password);\r\n }\r\n\r\n override send(body?: Document | XMLHttpRequestBodyInit | null): void {\r\n if (typeof body === 'string') {\r\n this._xhrRequestBody = parseJsonObject(body);\r\n }\r\n this.addEventListener('load', () => {\r\n try {\r\n handleXhrInterception(\r\n this._xhrMethod,\r\n this._xhrUrl,\r\n this._xhrRequestBody,\r\n this.responseText\r\n );\r\n } catch {\r\n // Never let monitoring errors surface\r\n }\r\n });\r\n super.send(body);\r\n }\r\n } as unknown as typeof XMLHttpRequest;\r\n }\r\n\r\n private uninstallXhr(): void {\r\n if (!this.originalXHR) return;\r\n window.XMLHttpRequest = this.originalXHR;\r\n this.originalXHR = null;\r\n }\r\n\r\n private async handleFetchInterception(\r\n input: RequestInfo | URL,\r\n init: RequestInit | undefined,\r\n responseClone: Response\r\n ): Promise<void> {\r\n const method = resolveMethod(input, init);\r\n if (!(INTERCEPTED_METHODS as readonly string[]).includes(method)) return;\r\n\r\n const url = resolveUrl(input);\r\n const alias = generateAlias(method, url);\r\n\r\n this.recording.registerInterceptor(method, url, alias);\r\n\r\n const extendedHttp = this.isExtendedHttpEnabled();\r\n const requestBody = extendedHttp ? parseRequestBody(init) : null;\r\n let responseBody: Record<string, unknown> | null = null;\r\n if (extendedHttp) {\r\n try {\r\n responseBody = parseJsonObject(await responseClone.text());\r\n } catch {\r\n // Unreadable body β continue without validations\r\n }\r\n }\r\n\r\n const cmd = buildCyWaitCommand(method, alias, extendedHttp, requestBody, responseBody);\r\n this.recording.addCommand(cmd);\r\n }\r\n\r\n private handleXhrInterception(\r\n method: string,\r\n url: string,\r\n requestBody: Record<string, unknown> | null,\r\n responseText: string\r\n ): void {\r\n if (!(INTERCEPTED_METHODS as readonly string[]).includes(method as InterceptedMethod)) return;\r\n\r\n const alias = generateAlias(method, url);\r\n this.recording.registerInterceptor(method, url, alias);\r\n\r\n const extendedHttp = this.isExtendedHttpEnabled();\r\n const responseBody = extendedHttp ? parseJsonObject(responseText) : null;\r\n\r\n const cmd = buildCyWaitCommand(method, alias, extendedHttp, requestBody, responseBody);\r\n this.recording.addCommand(cmd);\r\n }\r\n}\r\n\r\n","export const SCROLLBAR_STYLES = `\r\n.swal2-popup::-webkit-scrollbar,\r\n.swal2-html-container::-webkit-scrollbar,\r\n.swal2-content::-webkit-scrollbar,\r\n.swal2-container::-webkit-scrollbar {\r\n width: 5px;\r\n height: 5px;\r\n background: transparent;\r\n}\r\n.swal2-popup::-webkit-scrollbar-thumb,\r\n.swal2-html-container::-webkit-scrollbar-thumb,\r\n.swal2-content::-webkit-scrollbar-thumb,\r\n.swal2-container::-webkit-scrollbar-thumb {\r\n background: #30363d;\r\n border-radius: 3px;\r\n}\r\n.swal2-popup::-webkit-scrollbar-thumb:hover,\r\n.swal2-html-container::-webkit-scrollbar-thumb:hover,\r\n.swal2-content::-webkit-scrollbar-thumb:hover {\r\n background: #484f58;\r\n}\r\n.swal2-popup::-webkit-scrollbar-track,\r\n.swal2-html-container::-webkit-scrollbar-track,\r\n.swal2-content::-webkit-scrollbar-track,\r\n.swal2-container::-webkit-scrollbar-track {\r\n background: transparent;\r\n}\r\n.swal2-popup, .swal2-html-container, .swal2-content, .swal2-container {\r\n scrollbar-width: thin;\r\n scrollbar-color: #30363d transparent;\r\n}\r\n`;\r\n\r\nexport const LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES = `\r\n.swal2-container, .swal2-popup {\r\n z-index: 99999 !important;\r\n}\r\n.swal2-container {\r\n padding: 0 !important;\r\n align-items: center !important;\r\n justify-content: center !important;\r\n}\r\n.swal2-popup {\r\n background: #161b22 !important;\r\n color: #e6edf3 !important;\r\n border-radius: 12px !important;\r\n box-shadow: 0 24px 64px rgba(0,0,0,0.72), 0 0 0 1px #30363d !important;\r\n border: none !important;\r\n padding: 0 !important;\r\n min-width: 400px;\r\n max-width: 90vw;\r\n min-height: 200px;\r\n max-height: 90vh;\r\n}\r\n/* Override SweetAlert2 v11's display:grid on .swal2-popup.swal2-modal */\r\n.swal2-popup.swal2-modal {\r\n display: flex !important;\r\n flex-direction: column !important;\r\n align-items: stretch !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-header {\r\n flex-shrink: 0 !important;\r\n flex-grow: 0 !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-title {\r\n color: #e6edf3 !important;\r\n font-weight: 600 !important;\r\n font-size: 14px !important;\r\n background: #161b22;\r\n padding: 14px 48px 13px 18px !important;\r\n margin: 0 !important;\r\n border-bottom: 1px solid #21262d;\r\n text-align: left !important;\r\n letter-spacing: 0.1px;\r\n white-space: nowrap !important;\r\n overflow: hidden !important;\r\n text-overflow: ellipsis !important;\r\n}\r\n.swal2-close {\r\n position: absolute !important;\r\n top: 10px !important;\r\n right: 12px !important;\r\n color: #8b949e !important;\r\n font-size: 1.1rem !important;\r\n z-index: 1 !important;\r\n border-radius: 6px !important;\r\n width: 28px !important;\r\n height: 28px !important;\r\n line-height: 28px !important;\r\n transition: background 0.15s, color 0.15s !important;\r\n}\r\n.swal2-close:hover {\r\n background: #21262d !important;\r\n color: #e6edf3 !important;\r\n}\r\n/* In SweetAlert2 v11, .swal2-html-container is a direct child of .swal2-popup */\r\n.swal2-html-container {\r\n flex: 1 !important;\r\n min-height: 0 !important;\r\n background: #161b22;\r\n padding: 0 !important;\r\n margin: 0 !important;\r\n width: 100%;\r\n display: flex !important;\r\n flex-direction: column !important;\r\n align-items: stretch;\r\n box-sizing: border-box;\r\n overflow: hidden !important;\r\n}\r\n/* The single wrapper div we inject inside each modal fills the container */\r\n.swal2-html-container > div {\r\n flex: 1 !important;\r\n min-height: 0 !important;\r\n display: flex !important;\r\n flex-direction: column !important;\r\n overflow: hidden !important;\r\n}\r\n.swal2-actions, .swal2-footer {\r\n flex-shrink: 0 !important;\r\n flex-grow: 0 !important;\r\n}\r\n`;\r\n\r\nexport function injectStyles(css: string, id: string): void {\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement('style');\r\n style.id = id;\r\n style.innerHTML = css;\r\n document.head.appendChild(style);\r\n}\r\n","export function makeModalResizable(\r\n modal: HTMLElement,\r\n options?: { minWidth?: number; minHeight?: number }\r\n): () => void {\r\n if (!modal || modal.querySelector('.modal-resizer')) return () => { /* no-op */ };\r\n\r\n const rect = modal.getBoundingClientRect();\r\n modal.style.position = 'fixed';\r\n modal.style.top = `${rect.top}px`;\r\n modal.style.left = `${rect.left}px`;\r\n modal.style.width = `${rect.width}px`;\r\n modal.style.margin = '0';\r\n modal.style.resize = 'both';\r\n modal.style.overflow = 'hidden';\r\n modal.style.minWidth = (options?.minWidth ?? 320) + 'px';\r\n modal.style.minHeight = (options?.minHeight ?? 180) + 'px';\r\n\r\n const resizer = document.createElement('div');\r\n resizer.className = 'modal-resizer';\r\n resizer.style.position = 'absolute';\r\n resizer.style.width = '16px';\r\n resizer.style.height = '16px';\r\n resizer.style.right = '2px';\r\n resizer.style.bottom = '2px';\r\n resizer.style.cursor = 'nwse-resize';\r\n resizer.style.background = 'rgba(0,0,0,0.1)';\r\n resizer.style.zIndex = '10';\r\n modal.appendChild(resizer);\r\n\r\n let isResizing = false;\r\n let lastX = 0;\r\n let lastY = 0;\r\n\r\n const mouseMove = (e: MouseEvent): void => {\r\n if (!isResizing) return;\r\n const dx = e.clientX - lastX;\r\n const dy = e.clientY - lastY;\r\n lastX = e.clientX;\r\n lastY = e.clientY;\r\n const rect = modal.getBoundingClientRect();\r\n modal.style.width = rect.width + dx + 'px';\r\n modal.style.height = rect.height + dy + 'px';\r\n };\r\n\r\n const mouseUp = (): void => {\r\n isResizing = false;\r\n document.body.style.userSelect = '';\r\n };\r\n\r\n resizer.addEventListener('mousedown', (e) => {\r\n e.preventDefault();\r\n isResizing = true;\r\n lastX = e.clientX;\r\n lastY = e.clientY;\r\n document.body.style.userSelect = 'none';\r\n });\r\n\r\n window.addEventListener('mousemove', mouseMove);\r\n window.addEventListener('mouseup', mouseUp);\r\n\r\n return () => {\r\n window.removeEventListener('mousemove', mouseMove);\r\n window.removeEventListener('mouseup', mouseUp);\r\n if (resizer.parentNode) resizer.parentNode.removeChild(resizer);\r\n };\r\n}\r\n\r\nfunction applyDraggable(swal: HTMLElement, dragArea: HTMLElement): void {\r\n let isDragging = false;\r\n let offsetX = 0;\r\n let offsetY = 0;\r\n\r\n dragArea.style.cursor = 'move';\r\n dragArea.onmousedown = (e: MouseEvent) => {\r\n isDragging = true;\r\n const rect = swal.getBoundingClientRect();\r\n offsetX = e.clientX - rect.left;\r\n offsetY = e.clientY - rect.top;\r\n document.onmousemove = (ev: MouseEvent) => {\r\n if (isDragging) {\r\n swal.style.position = 'fixed';\r\n swal.style.margin = '0';\r\n swal.style.left = `${ev.clientX - offsetX}px`;\r\n swal.style.top = `${ev.clientY - offsetY}px`;\r\n }\r\n };\r\n document.onmouseup = () => {\r\n isDragging = false;\r\n document.onmousemove = null;\r\n document.onmouseup = null;\r\n };\r\n };\r\n}\r\n\r\nfunction resolveDragArea(swal: HTMLElement): HTMLElement | null {\r\n return (swal.querySelector('.swal2-header') as HTMLElement | null)\r\n ?? (swal.querySelector('.swal2-title') as HTMLElement | null);\r\n}\r\n\r\nexport function makeSwalDraggable(): void {\r\n const popups = document.querySelectorAll('.swal2-popup');\r\n if (!popups.length) return;\r\n const swal = popups[popups.length - 1] as HTMLElement;\r\n const dragArea = resolveDragArea(swal);\r\n if (!dragArea) return;\r\n applyDraggable(swal, dragArea);\r\n}\r\n\r\nexport function makeSwalDraggableByContentId(contentId: string): void {\r\n const content = document.getElementById(contentId);\r\n if (!content) {\r\n makeSwalDraggable();\r\n return;\r\n }\r\n const swal = (content.closest('.swal2-popup') as HTMLElement | null)\r\n ?? (document.querySelector('.swal2-popup') as HTMLElement | null);\r\n if (!swal) return;\r\n const dragArea = resolveDragArea(swal);\r\n if (!dragArea) return;\r\n applyDraggable(swal, dragArea);\r\n}\r\n\r\nexport function setSwal2DataCyAttribute(dataCy = 'lib-e2e-cypress-for-dummys'): void {\r\n document.querySelector('.swal2-container')?.setAttribute('data-cy', dataCy);\r\n document.querySelector('.swal2-html-container')?.setAttribute('data-cy', dataCy);\r\n document.querySelector('.swal2-title')?.setAttribute('data-cy', dataCy);\r\n}\r\n","export function showToast(message: string, isSuccess = true): void {\r\n const toast = document.createElement('div');\r\n toast.textContent = message;\r\n toast.style.position = 'fixed';\r\n toast.style.top = '30px';\r\n toast.style.right = '30px';\r\n toast.style.padding = '16px 24px';\r\n toast.style.background = isSuccess ? '#4caf50' : '#f44336';\r\n toast.style.color = '#fff';\r\n toast.style.borderRadius = '8px';\r\n toast.style.boxShadow = '0 2px 8px rgba(0,0,0,0.2)';\r\n toast.style.zIndex = '9999';\r\n toast.style.fontSize = '1rem';\r\n toast.style.fontWeight = 'bold';\r\n toast.style.pointerEvents = 'none';\r\n document.body.appendChild(toast);\r\n setTimeout(() => toast.remove(), 3000);\r\n}\r\n","import type { TestWithDetails } from '../services/persistence.service';\n\n/** How the user chose which tests to export. */\nexport type ExportMode = 'all' | 'manual' | 'tags';\n\nexport interface ExportSelectionOptions {\n /** Test ids to include in `manual` mode. */\n ids?: Iterable<number>;\n /** Tags to match in `tags` mode. */\n tags?: Iterable<string>;\n}\n\n/**\n * Returns the subset of tests to export for a given selection mode.\n *\n * - `all` β every test (a shallow copy).\n * - `manual` β tests whose id is in `opts.ids`. Empty/absent ids β none.\n * - `tags` β tests carrying at least one of `opts.tags` (OR semantics).\n * Empty/absent tags β none.\n *\n * Pure: never mutates its inputs.\n */\nexport function selectTestsForExport(\n tests: TestWithDetails[],\n mode: ExportMode,\n opts: ExportSelectionOptions = {},\n): TestWithDetails[] {\n if (mode === 'all') return [...tests];\n\n if (mode === 'manual') {\n const ids = new Set(opts.ids ?? []);\n return tests.filter((t) => ids.has(t.id));\n }\n\n // 'tags' β include a test if it carries ANY of the selected tags (OR).\n const tags = new Set(opts.tags ?? []);\n if (tags.size === 0) return [];\n return tests.filter((t) => (t.tags ?? []).some((tag) => tags.has(tag)));\n}\n","/**\n * True when a hostname refers to the local machine β used to gate dev-only\n * features (e.g. launching a Cypress run via the local runner) so they are\n * offered only when the app is served locally, not from a deployed environment.\n *\n * Treats as local: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, and the\n * empty hostname (e.g. file:// URLs). Case-insensitive.\n */\nexport function isLocalHost(hostname: string): boolean {\n if (!hostname) return true;\n const h = hostname.toLowerCase();\n return (\n h === 'localhost' ||\n h.endsWith('.localhost') ||\n h === '127.0.0.1' ||\n h === '::1' ||\n h === '0.0.0.0'\n );\n}\n","/**\r\n * Geometry helpers for the draggable recording widget (spec 007).\r\n * Pure functions β no DOM β so the drag/clamp/expansion logic is unit-testable\r\n * without real layout (jsdom returns 0-sized rects).\r\n */\r\n\r\nexport type ExpandDirection = 'up-left' | 'up-right' | 'down-left' | 'down-right';\r\n\r\nexport interface Point {\r\n x: number;\r\n y: number;\r\n}\r\n\r\n/** Toggle radius (44/2) + small gap, so the toggle never touches the edge. */\r\nexport const TOGGLE_MARGIN = 30;\r\n\r\n/** Pixels the pointer must travel before a press becomes a drag (vs a click). */\r\nexport const DRAG_THRESHOLD = 5;\r\n\r\n/** Distance, in px, from the bottom-right edges of the original (default) anchor. */\r\nconst DEFAULT_EDGE_OFFSET = 46;\r\n\r\n/**\r\n * Toggle-centre offset inside the 190Γ190 widget box, per expansion direction.\r\n * The toggle sits at the box corner nearest the screen edge so the arc always\r\n * expands toward the viewport interior (and stays inside the box / on screen).\r\n */\r\nexport function boxOffsetForDirection(dir: ExpandDirection): Point {\r\n return {\r\n x: dir.endsWith('left') ? 144 : 46,\r\n y: dir.startsWith('up') ? 144 : 46,\r\n };\r\n}\r\n\r\n/** Clamps the toggle-centre so the toggle button stays fully on screen. */\r\nexport function clampTogglePosition(\r\n x: number,\r\n y: number,\r\n vw: number,\r\n vh: number,\r\n margin: number = TOGGLE_MARGIN,\r\n): Point {\r\n const maxX = Math.max(margin, vw - margin);\r\n const maxY = Math.max(margin, vh - margin);\r\n return {\r\n x: Math.min(Math.max(x, margin), maxX),\r\n y: Math.min(Math.max(y, margin), maxY),\r\n };\r\n}\r\n\r\n/**\r\n * Chooses the radial expansion direction so the menu opens toward the centre of\r\n * the viewport (top half β expand down; left half β expand right).\r\n */\r\nexport function resolveExpandDirection(x: number, y: number, vw: number, vh: number): ExpandDirection {\r\n const vertical = y < vh / 2 ? 'down' : 'up';\r\n const horizontal = x < vw / 2 ? 'right' : 'left';\r\n return `${vertical}-${horizontal}` as ExpandDirection;\r\n}\r\n\r\n/** Default toggle-centre (bottom-right corner), matching the original CSS anchor. */\r\nexport function defaultTogglePosition(vw: number, vh: number): Point {\r\n return { x: vw - DEFAULT_EDGE_OFFSET, y: vh - DEFAULT_EDGE_OFFSET };\r\n}\r\n\r\n/** Box top-left for a given (clamped) toggle-centre and direction. */\r\nexport function boxTopLeftFor(toggleCentre: Point, dir: ExpandDirection): Point {\r\n const off = boxOffsetForDirection(dir);\r\n return { x: toggleCentre.x - off.x, y: toggleCentre.y - off.y };\r\n}\r\n","export const TEST_PREVISUALIZER_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .toolbar {\n display: flex; gap: 6px; padding: 10px 12px; flex-shrink: 0;\n background: #161b22; border-bottom: 1px solid #21262d;\n }\n button {\n padding: 5px 12px; border: none; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s; letter-spacing: 0.1px;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n button.active { background: #2f81f7; color: #fff; }\n .section { padding: 10px 12px; flex-shrink: 0; }\n .section.section-cmds { flex: 1; min-height: 0; display: flex; flex-direction: column; }\n .section-title {\n font-size: 10px; font-weight: 600; color: #484f58; text-transform: uppercase;\n letter-spacing: 0.8px; margin-bottom: 7px; flex-shrink: 0;\n }\n .list {\n overflow-y: auto; background: #0d1117;\n border-radius: 8px; padding: 6px 8px;\n border: 1px solid #21262d;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .section-cmds .list { flex: 1; min-height: 0; }\n .list::-webkit-scrollbar { width: 4px; }\n .list::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .item {\n display: flex; align-items: flex-start; gap: 6px;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 11px;\n color: #c9d1d9; padding: 4px 8px; border-radius: 4px;\n word-break: break-all; line-height: 1.65;\n border-left: 2px solid transparent;\n transition: background 0.1s, border-color 0.1s;\n }\n .item:hover { background: #161b22; border-left-color: #2f81f7; }\n .cmd-text { flex: 1; }\n .item-actions {\n display: flex; gap: 3px; flex-shrink: 0;\n opacity: 0; transition: opacity 0.15s;\n }\n .item:hover .item-actions { opacity: 1; }\n .btn-step {\n width: 20px; height: 20px; border: none; border-radius: 3px; cursor: pointer;\n font-size: 12px; background: transparent; color: #484f58;\n transition: background 0.12s, color 0.12s;\n display: flex; align-items: center; justify-content: center;\n padding: 0; line-height: 1;\n }\n .btn-step:hover { background: #30363d; color: #e6edf3; }\n .btn-step-del:hover { background: rgba(248,81,73,0.15); color: #f85149; }\n .empty { color: #484f58; font-size: 12px; padding: 20px 8px; text-align: center; }\n`;\n","import { escHtml } from '../../utils/html.utils';\n\nexport function renderTestPrevisualizer(\n commands: string[],\n interceptors: string[],\n showInterceptors: boolean,\n editable: boolean,\n t: (key: string) => string,\n): string {\n const editControls = (idx: number, total: number) => editable ? `\n <span class=\"item-actions\">\n <button class=\"btn-step\" data-move-up=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.UP_TITLE')}\" ${idx === 0 ? 'disabled style=\"opacity:.3\"' : ''}>β</button>\n <button class=\"btn-step\" data-move-dn=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DOWN_TITLE')}\" ${idx === total - 1 ? 'disabled style=\"opacity:.3\"' : ''}>β</button>\n <button class=\"btn-step btn-step-del\" data-del=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DEL_TITLE')}\">β</button>\n </span>` : '';\n\n const cmdItems = commands.length\n ? commands.map((c, i) => `\n <div class=\"item\">\n <span class=\"cmd-text\">${escHtml(c)}</span>\n ${editControls(i, commands.length)}\n </div>`).join('')\n : `<div class=\"empty\">${t('TEST_PREVISUALIZER.NO_CMDS_YET')}</div>`;\n\n const icpEditControls = (idx: number) => editable\n ? `<span class=\"item-actions\"><button class=\"btn-step btn-step-del\" data-del-icp=\"${idx}\" title=\"${t('TEST_PREVISUALIZER.DEL_TITLE')}\">β</button></span>`\n : '';\n\n const icpSection = showInterceptors\n ? `<div class=\"section\" data-section=\"interceptors\">\n <div class=\"section-title\">${t('TEST_PREVISUALIZER.INTERCEPTORS')}</div>\n <div class=\"list\">\n ${\n interceptors.length\n ? interceptors.map((ic, idx) => `\n <div class=\"item\">\n <span class=\"cmd-text\">${escHtml(ic)}</span>\n ${icpEditControls(idx)}\n </div>`).join('')\n : `<div class=\"empty\">${t('TEST_PREVISUALIZER.NO_ICP_SHORT')}</div>`\n }\n </div>\n <button style=\"margin-top:6px\" data-action=\"copy-icp\">${t('TEST_PREVISUALIZER.COPY_ICP_BTN')}</button>\n </div>`\n : '';\n\n return `\n <div class=\"toolbar\">\n <button data-action=\"copy\">${t('TEST_PREVISUALIZER.COPY_CMDS_BTN')}</button>\n <button data-action=\"toggle-icp\" class=\"${showInterceptors ? 'active' : ''}\">\n ${showInterceptors ? t('TEST_PREVISUALIZER.HIDE_INTERCEPTORS') : t('TEST_PREVISUALIZER.SHOW_INTERCEPTORS')} (${interceptors.length})\n </button>\n </div>\n <div class=\"section section-cmds\">\n <div class=\"section-title\">${t('TEST_PREVISUALIZER.SECTION_COMMANDS')} (${commands.length})</div>\n <div class=\"list\" data-ref=\"cmds\">${cmdItems}</div>\n </div>\n ${icpSection}`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { TEST_PREVISUALIZER_STYLES } from './test-previsualizer.styles';\r\nimport { renderTestPrevisualizer } from './test-previsualizer.template';\r\n\r\nexport class TestPrevisualizerElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private _commands: string[] = [];\r\n private _interceptors: string[] = [];\r\n private _showInterceptors = false;\r\n editable = false;\r\n translation: TranslationService = translationService;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n this.render();\r\n }\r\n\r\n get commands(): string[] {\r\n return this._commands;\r\n }\r\n set commands(v: string[]) {\r\n this._commands = v;\r\n this.render();\r\n }\r\n\r\n get interceptors(): string[] {\r\n return this._interceptors;\r\n }\r\n set interceptors(v: string[]) {\r\n this._interceptors = v;\r\n this.render();\r\n }\r\n\r\n get showInterceptors(): boolean {\r\n return this._showInterceptors;\r\n }\r\n\r\n toggleInterceptors(): void {\r\n this._showInterceptors = !this._showInterceptors;\r\n this.render();\r\n }\r\n\r\n copyToClipboard(): void {\r\n const text = this._commands.join('\\n');\r\n if (!text) return;\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n copyInterceptorsToClipboard(): void {\r\n const text = this._interceptors.join('\\n');\r\n if (!text) return;\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private dispatchDelete(index: number): void {\r\n this.dispatchEvent(new CustomEvent('deletecommand', { detail: index, bubbles: true, composed: true }));\r\n }\r\n\r\n private dispatchMove(from: number, to: number): void {\r\n this.dispatchEvent(new CustomEvent('movecommand', { detail: { from, to }, bubbles: true, composed: true }));\r\n }\r\n\r\n private dispatchDeleteInterceptor(index: number): void {\r\n this.dispatchEvent(new CustomEvent('deleteinterceptor', { detail: index, bubbles: true, composed: true }));\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${TEST_PREVISUALIZER_STYLES}</style>${renderTestPrevisualizer(\r\n this._commands,\r\n this._interceptors,\r\n this._showInterceptors,\r\n this.editable,\r\n this.t.bind(this),\r\n )}`;\r\n\r\n const cmdsEl = this.shadow.querySelector<HTMLElement>('[data-ref=\"cmds\"]');\r\n if (cmdsEl) cmdsEl.scrollTop = cmdsEl.scrollHeight;\r\n\r\n this.shadow.querySelector('[data-action=\"copy\"]')?.addEventListener('click', () => this.copyToClipboard());\r\n this.shadow.querySelector('[data-action=\"toggle-icp\"]')?.addEventListener('click', () => this.toggleInterceptors());\r\n this.shadow.querySelector('[data-action=\"copy-icp\"]')?.addEventListener('click', () => this.copyInterceptorsToClipboard());\r\n\r\n if (this.editable) {\r\n this.shadow.querySelectorAll('[data-del]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.dispatchDelete(Number((btn as HTMLElement).dataset['del']));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-move-up]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n const idx = Number((btn as HTMLElement).dataset['moveUp']);\r\n this.dispatchMove(idx, idx - 1);\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-move-dn]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n const idx = Number((btn as HTMLElement).dataset['moveDn']);\r\n this.dispatchMove(idx, idx + 1);\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-del-icp]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n e.stopPropagation();\r\n this.dispatchDeleteInterceptor(Number((btn as HTMLElement).dataset['delIcp']));\r\n });\r\n });\r\n }\r\n }\r\n}\r\n\r\nif (!customElements.get('test-previsualizer')) {\r\n customElements.define('test-previsualizer', TestPrevisualizerElement);\r\n}\r\n","export const SAVE_TEST_STYLES = `\n :host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n .container { padding: 24px 28px; text-align: left; }\n .btn-row, p { text-align: center; }\n p { margin: 0 0 20px; font-size: 14px; color: #8b949e; line-height: 1.5; }\n .btn-row { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; margin-top: 16px; }\n button {\n padding: 7px 16px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; transition: filter 0.15s, transform 0.1s;\n letter-spacing: 0.1px;\n }\n button:hover { filter: brightness(1.1); }\n button:active { transform: scale(0.97); }\n .btn-primary { background: #2f81f7; color: #fff; }\n .btn-success { background: #3fb950; color: #fff; }\n .btn-danger { background: transparent; color: #f85149; border: 1px solid rgba(248,81,73,0.5); }\n .btn-danger:hover { background: rgba(248,81,73,0.08); filter: none; }\n input[type=\"text\"] {\n width: 100%; padding: 10px 14px; border: 1px solid #30363d;\n border-radius: 8px; background: #0d1117; color: #e6edf3;\n font-size: 14px; outline: none; margin-bottom: 4px;\n transition: border-color 0.15s, box-shadow 0.15s;\n }\n input[type=\"text\"]:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }\n input[type=\"text\"]::placeholder { color: #484f58; }\n textarea {\n width: 100%; padding: 10px 14px; border: 1px solid #30363d;\n border-radius: 8px; background: #0d1117; color: #e6edf3;\n font-size: 14px; outline: none; margin-bottom: 4px;\n font-family: inherit; resize: vertical; line-height: 1.5;\n transition: border-color 0.15s, box-shadow 0.15s;\n }\n textarea:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.15); }\n textarea::placeholder { color: #484f58; }\n .tag-label {\n font-size: 11px; color: #484f58; text-align: left; margin-bottom: 5px; display: block;\n }\n .tag-input-row { display: flex; gap: 6px; margin-bottom: 8px; }\n .tag-input-row input[type=\"text\"] {\n font-size: 12px; padding: 6px 10px; margin: 0;\n }\n .btn-tag-add {\n padding: 6px 12px; font-size: 12px; background: #21262d; color: #8b949e;\n border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n transition: background 0.15s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-tag-add:hover { background: #30363d; color: #e6edf3; filter: none; }\n .chips { display: flex; flex-wrap: wrap; gap: 5px; min-height: 24px; text-align: left; }\n .chip {\n display: inline-flex; align-items: center; gap: 5px;\n background: rgba(47,129,247,0.15); color: #2f81f7;\n border: 1px solid rgba(47,129,247,0.3); border-radius: 20px;\n padding: 2px 10px 2px 10px; font-size: 11px; font-weight: 500;\n }\n .chip-del {\n cursor: pointer; color: #8b949e; font-size: 12px; line-height: 1;\n transition: color 0.12s; padding: 0; background: none; border: none;\n }\n .chip-del:hover { color: #f85149; filter: none; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\n\nexport function renderSaveTestAsk(t: (key: string) => string): string {\n return `\n <div class=\"container\">\n <p>${t('SAVE_TEST.ASK')}</p>\n <div class=\"btn-row\">\n <button class=\"btn-primary\" id=\"btn-yes\">${t('SAVE_TEST.YES_CONTINUE')}</button>\n <button class=\"btn-danger\" id=\"btn-no\">${t('SAVE_TEST.NO_DISCARD')}</button>\n </div>\n </div>`;\n}\n\nexport function renderSaveTestDesc(description: string, notes: string, tags: string[], t: (key: string) => string): string {\n const chipsHtml = tags.map((tag) =>\n `<span class=\"chip\">${escHtml(tag)}<button class=\"chip-del\" data-tag=\"${escAttr(tag)}\" title=\"${t('SAVE_TEST.REMOVE_TAG_TITLE')}\">β</button></span>`\n ).join('');\n\n return `\n <div class=\"container\">\n <p>${t('SAVE_TEST.DESC_LABEL')} (<code>it()</code>):</p>\n <input id=\"desc-input\" type=\"text\" placeholder=\"${t('SAVE_TEST.DESC_PLACEHOLDER')}\"\n value=\"${escAttr(description)}\" autocomplete=\"off\" />\n <span class=\"tag-label\">${t('SAVE_TEST.NOTES_LABEL')}</span>\n <textarea id=\"notes-input\" rows=\"3\" placeholder=\"${escAttr(t('SAVE_TEST.NOTES_PLACEHOLDER'))}\">${escHtml(notes)}</textarea>\n <span class=\"tag-label\">${t('SAVE_TEST.TAGS_LABEL')}</span>\n <div class=\"tag-input-row\">\n <input id=\"tag-input\" type=\"text\" placeholder=\"${t('SAVE_TEST.TAGS_PLACEHOLDER')}\" autocomplete=\"off\" />\n <button class=\"btn-tag-add\" id=\"btn-add-tag\">${t('SAVE_TEST.ADD_TAG')}</button>\n </div>\n <div class=\"chips\" id=\"chips-container\">${chipsHtml || `<span style=\"color:#484f58;font-size:11px\">${t('SAVE_TEST.NO_TAGS')}</span>`}</div>\n <div class=\"btn-row\">\n <button class=\"btn-primary\" id=\"btn-confirm\">${t('SAVE_TEST.SAVE_BTN')}</button>\n <button class=\"btn-success\" id=\"btn-export\">${t('SAVE_TEST.SAVE_AND_EDIT')}</button>\n <button class=\"btn-danger\" id=\"btn-cancel\">${t('SAVE_TEST.CANCEL')}</button>\n </div>\n </div>`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\nimport { SAVE_TEST_STYLES } from './save-test.styles';\nimport { renderSaveTestAsk, renderSaveTestDesc } from './save-test.template';\n\nexport class SaveTestElement extends HTMLElement {\n private shadow: ShadowRoot;\n private _step: 'ask' | 'desc' = 'ask';\n description = '';\n notes = '';\n tags: string[] = [];\n translation: TranslationService = translationService;\n\n constructor() {\n super();\n this.shadow = this.attachShadow({ mode: 'open' });\n }\n\n connectedCallback(): void { this.render(); }\n\n get step(): 'ask' | 'desc' { return this._step; }\n\n askSave(): void { this._step = 'desc'; this.render(); }\n\n confirmSave(): void { this.dispatch('savetest', { description: this.description.trim(), notes: this.notes, tags: [...this.tags] }); }\n\n confirmSaveAndExport(): void { this.dispatch('saveandexport', { description: this.description.trim(), notes: this.notes, tags: [...this.tags] }); }\n\n cancel(): void { this.dispatch('savetest', { description: null, notes: '', tags: [] }); }\n\n restartComponent(): void { this._step = 'ask'; this.description = ''; this.notes = ''; this.tags = []; this.render(); }\n\n addTag(tag: string): void {\n const t = tag.trim().replace(/[,;]/g, '');\n if (t && !this.tags.includes(t)) {\n this.tags = [...this.tags, t];\n this.render();\n }\n }\n\n removeTag(tag: string): void {\n this.tags = this.tags.filter((t) => t !== tag);\n this.render();\n }\n\n private t(key: string): string { return this.translation.translate(key); }\n\n private dispatch(type: string, detail: { description: string | null; notes: string; tags: string[] }): void {\n this.dispatchEvent(new CustomEvent(type, { detail, bubbles: true, composed: true }));\n }\n\n private render(): void {\n if (this._step === 'ask') {\n this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestAsk(this.t.bind(this))}`;\n this.shadow.getElementById('btn-yes')?.addEventListener('click', () => this.askSave());\n this.shadow.getElementById('btn-no')?.addEventListener('click', () => this.cancel());\n } else {\n this.shadow.innerHTML = `<style>${SAVE_TEST_STYLES}</style>${renderSaveTestDesc(this.description, this.notes, this.tags, this.t.bind(this))}`;\n\n const descInput = this.shadow.getElementById('desc-input') as HTMLInputElement;\n const notesInput = this.shadow.getElementById('notes-input') as HTMLTextAreaElement;\n const tagInput = this.shadow.getElementById('tag-input') as HTMLInputElement;\n\n descInput.addEventListener('input', () => { this.description = descInput.value; });\n notesInput.addEventListener('input', () => { this.notes = notesInput.value; });\n\n const tryAddTag = () => {\n this.addTag(tagInput.value);\n tagInput.value = '';\n };\n this.shadow.getElementById('btn-add-tag')?.addEventListener('click', tryAddTag);\n tagInput.addEventListener('keydown', (e: KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ',') { e.preventDefault(); tryAddTag(); }\n });\n\n this.shadow.querySelectorAll<HTMLButtonElement>('.chip-del').forEach((btn) => {\n btn.addEventListener('click', () => this.removeTag(btn.dataset['tag'] ?? ''));\n });\n\n this.shadow.getElementById('btn-confirm')?.addEventListener('click', () => this.confirmSave());\n this.shadow.getElementById('btn-export')?.addEventListener('click', () => this.confirmSaveAndExport());\n this.shadow.getElementById('btn-cancel')?.addEventListener('click', () => this.cancel());\n setTimeout(() => descInput.focus(), 60);\n }\n }\n}\n\nif (!customElements.get('save-test')) {\n customElements.define('save-test', SaveTestElement);\n}\n","export const TEST_EDITOR_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .toolbar {\n display: flex; align-items: center; gap: 6px; padding: 8px 10px; flex-shrink: 0;\n background: #161b22; border-bottom: 1px solid #21262d; flex-wrap: wrap;\n }\n .tag-filter { display: flex; gap: 5px; flex-wrap: wrap; flex: 1; }\n .tag-chip {\n padding: 2px 10px; border-radius: 20px; cursor: pointer; font-size: 11px; font-weight: 500;\n border: 1px solid #30363d; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s, border-color 0.12s;\n }\n .tag-chip:hover { background: #30363d; color: #e6edf3; }\n .tag-chip.active { background: rgba(47,129,247,0.2); color: #2f81f7; border-color: rgba(47,129,247,0.4); }\n .btn-select {\n padding: 4px 12px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-select:hover { background: #30363d; color: #e6edf3; }\n .btn-select.active { background: rgba(47,129,247,0.15); color: #2f81f7; border-color: rgba(47,129,247,0.3); }\n .describe-bar {\n display: flex; align-items: center; gap: 8px; padding: 8px 10px;\n background: rgba(47,129,247,0.06); border-bottom: 1px solid rgba(47,129,247,0.2);\n flex-wrap: wrap;\n }\n .describe-bar input {\n flex: 1; min-width: 150px; padding: 5px 10px; background: #0d1117;\n border: 1px solid #30363d; border-radius: 6px; color: #e6edf3;\n font-size: 12px; outline: none;\n }\n .describe-bar input:focus { border-color: #2f81f7; }\n .btn-gen-describe {\n padding: 5px 14px; border: 1px solid #2f81f7; border-radius: 6px; cursor: pointer;\n font-size: 11px; font-weight: 500; background: rgba(47,129,247,0.15); color: #2f81f7;\n transition: background 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-gen-describe:hover { background: rgba(47,129,247,0.25); }\n .selected-count { font-size: 11px; color: #8b949e; }\n .describe-bar { flex-shrink: 0; }\n .list { padding: 8px; flex: 1; min-height: 0; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent; }\n .list::-webkit-scrollbar { width: 4px; }\n .list::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .empty { color: #484f58; text-align: center; padding: 32px; font-size: 13px; }\n .row {\n background: #0d1117; border-radius: 8px; margin-bottom: 6px;\n overflow: hidden; border: 1px solid #21262d;\n transition: border-color 0.15s;\n }\n .row:hover { border-color: #30363d; }\n .row.selected-row { border-color: rgba(47,129,247,0.5); }\n .row-header {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 12px; cursor: pointer; user-select: none;\n }\n .row-header:hover { background: rgba(48,54,61,0.3); }\n .test-name { flex: 1; font-size: 13px; font-weight: 500; color: #e6edf3; }\n .test-date { font-size: 10.5px; color: #484f58; margin-right: 4px; }\n .test-tags { display: flex; gap: 4px; margin-right: 4px; }\n .test-tag {\n padding: 1px 7px; border-radius: 20px; font-size: 10px;\n background: rgba(47,129,247,0.1); color: #8b949e; border: 1px solid rgba(47,129,247,0.2);\n }\n .btn-icon {\n padding: 3px 8px; border: none; border-radius: 6px; cursor: pointer;\n font-size: 11px; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n .btn-icon:hover { background: #30363d; color: #e6edf3; }\n .btn-del:hover { background: rgba(248,81,73,0.15); color: #f85149; }\n input[type=\"checkbox\"] {\n width: 14px; height: 14px; accent-color: #2f81f7; cursor: pointer; flex-shrink: 0;\n }\n .row-body {\n background: #0d1117; padding: 10px 14px;\n border-top: 1px solid #21262d;\n }\n .test-notes {\n margin: 0 0 10px; padding: 8px 12px;\n background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);\n border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;\n line-height: 1.6; white-space: pre-wrap; word-break: break-word;\n }\n .code-preview {\n margin: 0; padding: 10px 12px; background: #161b22;\n border-radius: 6px; border: 1px solid #21262d;\n font-size: 11px; color: #c9d1d9; line-height: 1.7;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n overflow-x: auto; white-space: pre;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .code-preview::-webkit-scrollbar { height: 4px; }\n .code-preview::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .code-preview-icp { margin-top: 8px; }\n .sh-kw { color: #ff7b72; }\n .sh-bi { color: #d2a8ff; }\n .sh-str { color: #a5d6ff; }\n .sh-cmt { color: #8b949e; font-style: italic; }\n .sh-num { color: #79c0ff; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\nimport { syntaxHighlight } from '../../utils/syntax-highlight.utils';\nimport { normalizeBlock, escapeSingleQuotes } from '../../utils/code-format.utils';\nimport type { TestWithDetails } from '../../services/persistence.service';\n\nexport interface TestEditorState {\n tags: string[];\n visible: TestWithDetails[];\n selectedVisible: TestWithDetails[];\n activeTag: string | null;\n selectMode: boolean;\n selectedIds: Set<number>;\n describeName: string;\n expandedIndex: number | null;\n interceptorsByTest: Record<number, string[]>;\n locale: string;\n}\n\nexport function renderTestEditor(state: TestEditorState, t: (key: string) => string): string {\n const { tags, visible, selectedVisible, activeTag, selectMode, selectedIds, describeName, expandedIndex, interceptorsByTest, locale } = state;\n\n const tagFilterHtml = tags.length\n ? `<div class=\"tag-filter\">\n ${tags.map((tag) => `<button class=\"tag-chip${activeTag === tag ? ' active' : ''}\" data-filter-tag=\"${escAttr(tag)}\">${escHtml(tag)}</button>`).join('')}\n </div>`\n : `<div class=\"tag-filter\" style=\"color:#484f58;font-size:11px\">${t('TEST_EDITOR.NO_TAGS')}</div>`;\n\n const describeBarHtml = selectMode && selectedVisible.length > 0\n ? `<div class=\"describe-bar\">\n <span class=\"selected-count\">${selectedVisible.length} ${selectedVisible.length !== 1 ? t('TEST_EDITOR.SELECTED_PLURAL') : t('TEST_EDITOR.SELECTED_SINGULAR')}</span>\n <input id=\"describe-name\" type=\"text\" placeholder=\"${t('TEST_EDITOR.DESCRIBE_PLACEHOLDER')}\" value=\"${escAttr(describeName)}\" />\n <button class=\"btn-gen-describe\" id=\"btn-gen-describe\">${t('TEST_EDITOR.COPY_DESCRIBE')}</button>\n </div>`\n : '';\n\n const rows = visible.map((test, i) => {\n const expanded = expandedIndex === i;\n const date = new Date(test.createdAt).toLocaleString(locale, { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' });\n const icps = interceptorsByTest[test.id] ?? test.interceptors ?? [];\n const tagsHtml = (test.tags ?? []).length\n ? `<span class=\"test-tags\">${(test.tags ?? []).map((tag) => `<span class=\"test-tag\">${escHtml(tag)}</span>`).join('')}</span>`\n : '';\n const checkbox = selectMode\n ? `<input type=\"checkbox\" ${selectedIds.has(test.id) ? 'checked' : ''} data-select=\"${test.id}\" />`\n : '';\n const hasIcps = (test.interceptors ?? []).length > 0;\n const itBlockCode = `it('${escapeSingleQuotes(test.name)}', () => {\\n${(test.commands ?? []).map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});`;\n const icpBlockCode = icps.length ? `beforeEach(() => {\\n // Auto-generated Cypress interceptors\\n${icps.map(c => normalizeBlock(c, ' ')).join('\\n')}\\n});` : '';\n const notesHtml = (expanded && test.notes)\n ? `<p class=\"test-notes\">${escHtml(test.notes)}</p>`\n : '';\n const body = expanded ? `\n <div class=\"row-body\">\n ${notesHtml}\n <pre class=\"code-preview\">${syntaxHighlight(itBlockCode)}</pre>\n ${icpBlockCode ? `<pre class=\"code-preview code-preview-icp\">${syntaxHighlight(icpBlockCode)}</pre>` : ''}\n </div>` : '';\n return `\n <div class=\"row${selectedIds.has(test.id) ? ' selected-row' : ''}\">\n <div class=\"row-header\" data-action=\"expand\" data-idx=\"${i}\">\n ${checkbox}\n <span class=\"test-name\">${escHtml(test.name)}</span>\n ${tagsHtml}\n <span class=\"test-date\">${date}</span>\n <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>\n ${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>` : ''}\n <button class=\"btn-icon btn-del\" data-action=\"delete\" data-id=\"${test.id}\" title=\"${t('TEST_EDITOR.DELETE_TITLE')}\">π</button>\n </div>\n ${body}\n </div>`;\n }).join('');\n\n return `\n <div class=\"toolbar\">\n ${tagFilterHtml}\n <button class=\"btn-select${selectMode ? ' active' : ''}\" id=\"btn-select-mode\">\n ${selectMode ? t('TEST_EDITOR.CANCEL_SELECT') : t('TEST_EDITOR.MULTI_SELECT')}\n </button>\n </div>\n ${describeBarHtml}\n <div class=\"list\">\n ${visible.length ? rows : `<div class=\"empty\">${t('TEST_EDITOR.NO_TESTS')}</div>`}\n </div>`;\n}\n","import { escHtml } from './html.utils';\n\nconst KEYWORDS = new Set([\n 'describe', 'it', 'xit', 'fit', 'xdescribe', 'fdescribe',\n 'beforeEach', 'afterEach', 'before', 'after', 'context',\n 'const', 'let', 'var', 'function', 'return', 'if', 'else',\n 'import', 'export', 'from', 'new', 'this', 'null', 'undefined',\n 'true', 'false', 'async', 'await', 'of', 'in', 'typeof', 'void',\n]);\n\nconst BUILTINS = new Set(['cy', 'expect', 'assert', 'Cypress', 'chai']);\n\nexport function syntaxHighlight(code: string): string {\n return code.split('\\n').map(highlightLine).join('\\n');\n}\n\nfunction highlightLine(line: string): string {\n let result = '';\n let i = 0;\n const len = line.length;\n\n while (i < len) {\n // Single-line comment\n if (line[i] === '/' && i + 1 < len && line[i + 1] === '/') {\n result += `<span class=\"sh-cmt\">${escHtml(line.slice(i))}</span>`;\n return result;\n }\n // String literal (single, double, or template)\n const q = line[i];\n if (q === \"'\" || q === '\"' || q === '`') {\n let j = i + 1;\n while (j < len) {\n if (line[j] === '\\\\') { j += 2; continue; }\n if (line[j] === q) { j++; break; }\n j++;\n }\n result += `<span class=\"sh-str\">${escHtml(line.slice(i, j))}</span>`;\n i = j;\n continue;\n }\n // Number (not preceded by identifier character)\n if (/[0-9]/.test(line[i]) && (i === 0 || !/[a-zA-Z_$]/.test(line[i - 1]))) {\n let j = i;\n while (j < len && /[0-9.]/.test(line[j])) j++;\n result += `<span class=\"sh-num\">${escHtml(line.slice(i, j))}</span>`;\n i = j;\n continue;\n }\n // Identifier, keyword, or builtin\n if (/[a-zA-Z_$]/.test(line[i])) {\n let j = i;\n while (j < len && /[a-zA-Z0-9_$]/.test(line[j])) j++;\n const word = line.slice(i, j);\n if (KEYWORDS.has(word)) {\n result += `<span class=\"sh-kw\">${escHtml(word)}</span>`;\n } else if (BUILTINS.has(word)) {\n result += `<span class=\"sh-bi\">${escHtml(word)}</span>`;\n } else {\n result += escHtml(word);\n }\n i = j;\n continue;\n }\n result += escHtml(line[i]);\n i++;\n }\n return result;\n}\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\nimport { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { localeForLang } from '../../models/lang.model';\r\nimport { escapeSingleQuotes } from '../../utils/code-format.utils';\r\nimport { TEST_EDITOR_STYLES } from './test-editor.styles';\r\nimport { renderTestEditor } from './test-editor.template';\r\n\r\nexport class TestEditorElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n persistence!: PersistenceService;\r\n translation: TranslationService = translationService;\r\n tests: TestWithDetails[] = [];\r\n expandedIndex: number | null = null;\r\n interceptorsByTest: Record<number, string[]> = {};\r\n activeTag: string | null = null;\r\n selectMode = false;\r\n selectedIds: Set<number> = new Set();\r\n describeName = '';\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n this.loadTests();\r\n }\r\n\r\n async loadTests(): Promise<void> {\r\n this.tests = await this.persistence.getAllTests();\r\n this.render();\r\n }\r\n\r\n async deleteTest(id: number): Promise<void> {\r\n await this.persistence.deleteTest(id);\r\n this.selectedIds.delete(id);\r\n await this.loadTests();\r\n }\r\n\r\n toggleExpand(index: number): void {\r\n this.expandedIndex = this.expandedIndex === index ? null : index;\r\n if (this.expandedIndex !== null) {\r\n const test = this.tests[this.expandedIndex];\r\n if (test?.id && !this.interceptorsByTest[test.id]) {\r\n this.interceptorsByTest[test.id] = Array.isArray(test.interceptors) ? test.interceptors : [];\r\n }\r\n }\r\n this.render();\r\n }\r\n\r\n hasInterceptors(testId: number): boolean {\r\n return Array.isArray(this.interceptorsByTest[testId]) && this.interceptorsByTest[testId].length > 0;\r\n }\r\n\r\n toggleSelectMode(): void {\r\n this.selectMode = !this.selectMode;\r\n if (!this.selectMode) this.selectedIds.clear();\r\n this.render();\r\n }\r\n\r\n toggleSelectTest(id: number): void {\r\n if (this.selectedIds.has(id)) this.selectedIds.delete(id);\r\n else this.selectedIds.add(id);\r\n this.render();\r\n }\r\n\r\n generateDescribe(): void {\r\n const selected = this.tests.filter((t) => this.selectedIds.has(t.id));\r\n if (!selected.length) return;\r\n\r\n const name = this.describeName.trim() || this.t('TEST_EDITOR.DEFAULT_DESCRIBE');\r\n\r\n const allInterceptors = [...new Set(\r\n selected.flatMap((t) => this.interceptorsByTest[t.id] ?? t.interceptors ?? [])\r\n )];\r\n\r\n const beforeEach = allInterceptors.length\r\n ? ` beforeEach(() => {\\n // Auto-generated Cypress interceptors\\n ${allInterceptors.join('\\n ')}\\n });\\n\\n`\r\n : '';\r\n\r\n const itBlocks = selected\r\n .map((t) => {\r\n const cmds = (t.commands ?? []).map((c) => ` ${c}`).join('\\n');\r\n return ` it('${escapeSingleQuotes(t.name ?? '')}', () => {\\n${cmds}\\n });`;\r\n })\r\n .join('\\n\\n');\r\n\r\n const block = `describe('${escapeSingleQuotes(name)}', () => {\\n${beforeEach}${itBlocks}\\n});`;\r\n navigator.clipboard?.writeText(block);\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n get allTags(): string[] {\r\n const tagSet = new Set<string>();\r\n this.tests.forEach((t) => (t.tags ?? []).forEach((tag) => tagSet.add(tag)));\r\n return [...tagSet].sort();\r\n }\r\n\r\n get visibleTests(): TestWithDetails[] {\r\n const tag = this.activeTag;\r\n if (!tag) return this.tests;\r\n return this.tests.filter((t) => (t.tags ?? []).includes(tag));\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private render(): void {\r\n const tags = this.allTags;\r\n const visible = this.visibleTests;\r\n const selectedVisible = visible.filter((t) => this.selectedIds.has(t.id));\r\n\r\n this.shadow.innerHTML = `<style>${TEST_EDITOR_STYLES}</style>${renderTestEditor({\r\n tags,\r\n visible,\r\n selectedVisible,\r\n activeTag: this.activeTag,\r\n selectMode: this.selectMode,\r\n selectedIds: this.selectedIds,\r\n describeName: this.describeName,\r\n expandedIndex: this.expandedIndex,\r\n interceptorsByTest: this.interceptorsByTest,\r\n locale: localeForLang(this.translation.getLang()),\r\n }, this.t.bind(this))}`;\r\n\r\n this.shadow.getElementById('btn-select-mode')?.addEventListener('click', () => this.toggleSelectMode());\r\n\r\n this.shadow.querySelectorAll('[data-filter-tag]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const tag = (el as HTMLElement).dataset['filterTag'] ?? '';\r\n if (!tag) return;\r\n this.activeTag = this.activeTag === tag ? null : tag;\r\n this.render();\r\n });\r\n });\r\n\r\n const descInput = this.shadow.getElementById('describe-name') as HTMLInputElement | null;\r\n if (descInput) {\r\n descInput.addEventListener('input', () => { this.describeName = descInput.value; });\r\n }\r\n this.shadow.getElementById('btn-gen-describe')?.addEventListener('click', () => {\r\n this.describeName = descInput?.value ?? this.describeName;\r\n this.generateDescribe();\r\n });\r\n\r\n this.shadow.querySelectorAll('[data-select]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n this.toggleSelectTest(Number((el as HTMLElement).dataset['select']));\r\n });\r\n });\r\n\r\n this.shadow.querySelectorAll('[data-action=\"expand\"]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n if (this.selectMode) {\r\n const row = visible[Number((el as HTMLElement).dataset['idx'])];\r\n if (row) this.toggleSelectTest(row.id);\r\n } else {\r\n this.toggleExpand(Number((el as HTMLElement).dataset['idx']));\r\n }\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"delete\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n this.deleteTest(Number((el as HTMLElement).dataset['id']));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"copy-cmds\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n const idx = Number((el as HTMLElement).dataset['idx']);\r\n this.copyToClipboard((visible[idx]?.commands ?? []).join('\\n'));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-action=\"copy-icps\"]').forEach((el) => {\r\n el.addEventListener('click', (ev) => {\r\n ev.stopPropagation();\r\n const idx = Number((el as HTMLElement).dataset['idx']);\r\n const t = visible[idx];\r\n this.copyToClipboard((this.interceptorsByTest[t?.id] ?? t?.interceptors ?? []).join('\\n'));\r\n });\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('test-editor')) {\r\n customElements.define('test-editor', TestEditorElement);\r\n}\r\n","export const CONFIGURATION_STYLES = `\n :host { display: block; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n\n /* ββ Grid container βββββββββββββββββββββββββββββββββββββ */\n .cfg-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n padding: 14px;\n }\n\n /* ββ Cards ββββββββββββββββββββββββββββββββββββββββββββββ */\n .card {\n background: #161b22;\n border: 1px solid #21262d;\n border-radius: 10px;\n padding: 14px 16px;\n transition: border-color 0.15s;\n }\n .card:hover { border-color: #30363d; }\n .card-wide { grid-column: 1 / -1; }\n\n /* ββ Card header ββββββββββββββββββββββββββββββββββββββββ */\n .card-hd {\n display: flex; align-items: center; gap: 7px;\n font-size: 10px; font-weight: 700; text-transform: uppercase;\n letter-spacing: 0.8px; color: #484f58; margin-bottom: 12px;\n }\n .card-hd-icon { font-size: 13px; }\n\n /* ββ Language βββββββββββββββββββββββββββββββββββββββββββ */\n .field-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }\n .field-label { font-size: 12px; color: #8b949e; }\n select {\n background: #0d1117; color: #e6edf3; border: 1px solid #30363d;\n border-radius: 6px; padding: 6px 10px; font-size: 12px; outline: none;\n cursor: pointer; transition: border-color 0.15s; flex-shrink: 0;\n }\n select:focus { border-color: #2f81f7; box-shadow: 0 0 0 3px rgba(47,129,247,0.12); }\n\n /* ββ HTTP toggle ββββββββββββββββββββββββββββββββββββββββ */\n .check-row {\n display: flex; align-items: flex-start; gap: 10px;\n cursor: pointer; user-select: none;\n }\n input[type=\"checkbox\"] { width: 15px; height: 15px; margin-top: 2px; cursor: pointer; accent-color: #2f81f7; flex-shrink: 0; }\n .check-title { font-size: 12px; color: #c9d1d9; margin-bottom: 3px; }\n .check-sub { font-size: 10px; color: #484f58; line-height: 1.5; }\n\n /* ββ Cypress folder βββββββββββββββββββββββββββββββββββββ */\n .fs-layout { display: flex; gap: 12px; align-items: flex-start; }\n .fs-tree {\n flex-shrink: 0;\n margin: 0; padding: 8px 10px;\n background: #0d1117; border: 1px solid #21262d; border-radius: 6px;\n font-size: 10px; color: #c9d1d9; line-height: 1.8;\n font-family: 'Cascadia Code','Fira Code','Consolas',monospace;\n }\n .fs-right { display: flex; flex-direction: column; gap: 10px; flex: 1; }\n .fs-status {\n display: flex; align-items: center; gap: 8px;\n font-size: 12px; color: #8b949e;\n background: #0d1117; border: 1px solid #21262d; border-radius: 6px;\n padding: 8px 10px;\n }\n .fs-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }\n .fs-dot.on { background: #3fb950; box-shadow: 0 0 6px rgba(63,185,80,.5); }\n .fs-dot.off { background: #484f58; }\n .fs-folder { color: #e6edf3; font-family: 'Cascadia Code','Fira Code','Consolas',monospace; font-size: 11px; }\n\n /* ββ Buttons ββββββββββββββββββββββββββββββββββββββββββββ */\n .btn-row { display: flex; gap: 8px; flex-wrap: wrap; }\n button {\n padding: 7px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s, border-color 0.15s;\n }\n button:hover { background: #30363d; color: #e6edf3; border-color: #484f58; }\n .btn-import {\n display: inline-block;\n padding: 7px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s, border-color 0.15s;\n }\n .btn-import:hover { background: #30363d; color: #e6edf3; border-color: #484f58; }\n .btn-danger { border-color: rgba(248,81,73,.4); color: #f85149; background: transparent; }\n .btn-danger:hover { background: rgba(248,81,73,.08); border-color: #f85149; color: #f85149; }\n .file-input { display: none; }\n\n /* ββ Data section desc ββββββββββββββββββββββββββββββββββ */\n .data-desc { font-size: 11px; color: #484f58; margin-bottom: 10px; line-height: 1.5; }\n\n /* ββ Export overlay (modal) βββββββββββββββββββββββββββββ */\n .export-overlay {\n position: fixed; inset: 0; z-index: 100000;\n background: rgba(1,4,9,0.7);\n display: flex; align-items: center; justify-content: center; padding: 20px;\n }\n .export-modal {\n width: 640px; max-width: 100%; max-height: 86vh;\n display: flex; flex-direction: column;\n background: #161b22; border: 1px solid #30363d; border-radius: 12px;\n box-shadow: 0 12px 40px rgba(0,0,0,0.5); overflow: hidden;\n }\n .export-hd {\n padding: 14px 18px; font-size: 13px; font-weight: 700;\n border-bottom: 1px solid #21262d; color: #e6edf3;\n }\n .export-modes { display: flex; gap: 6px; padding: 12px 18px 0; }\n .export-mode {\n flex: 1; padding: 7px 10px; font-size: 11px; border-radius: 6px;\n background: #0d1117; border: 1px solid #30363d; color: #8b949e;\n }\n .export-mode:hover { background: #21262d; color: #e6edf3; }\n .export-mode.active { background: rgba(47,129,247,0.15); border-color: #2f81f7; color: #2f81f7; }\n .export-body {\n padding: 14px 18px; overflow-y: auto; flex: 1; min-height: 160px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .export-tag-hint { font-size: 12px; color: #484f58; margin-top: 12px; }\n .export-result-label {\n font-size: 10px; color: #484f58; text-transform: uppercase; letter-spacing: 0.6px;\n font-weight: 600; margin: 14px 0 6px;\n }\n .export-row-static { cursor: default; }\n .export-row-static:hover { background: transparent; }\n .export-all-desc { font-size: 12px; color: #8b949e; }\n .export-empty { font-size: 12px; color: #484f58; text-align: center; padding: 20px; }\n .export-list { display: flex; flex-direction: column; gap: 4px; }\n .export-row {\n display: flex; align-items: center; gap: 8px;\n padding: 6px 8px; border-radius: 6px; cursor: pointer; font-size: 12px; color: #c9d1d9;\n }\n .export-row:hover { background: #0d1117; }\n .export-row-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n .export-row-tag {\n font-size: 9px; color: #8b949e; background: #0d1117;\n border: 1px solid #30363d; border-radius: 10px; padding: 1px 7px; flex-shrink: 0;\n }\n .export-tags { display: flex; flex-wrap: wrap; gap: 6px; }\n .export-tag {\n padding: 4px 10px; font-size: 11px; border-radius: 12px;\n background: #0d1117; border: 1px solid #30363d; color: #8b949e;\n }\n .export-tag:hover { background: #21262d; color: #e6edf3; }\n .export-tag.active { background: rgba(47,129,247,0.15); border-color: #2f81f7; color: #2f81f7; }\n .export-ft {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n padding: 12px 18px; border-top: 1px solid #21262d;\n }\n .export-count { font-size: 11px; color: #8b949e; }\n .export-count b { color: #e6edf3; }\n .export-ft-actions { display: flex; gap: 8px; }\n .btn-export-confirm { background: #238636; border-color: #238636; color: #fff; }\n .btn-export-confirm:hover:not(:disabled) { background: #2ea043; border-color: #2ea043; }\n .btn-export-confirm:disabled { opacity: 0.45; cursor: not-allowed; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\r\nimport { selectTestsForExport, type ExportMode } from '../../utils/export-selection.utils';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\n\r\nexport const LANGS = [\r\n { value: 'es', label: 'EspaΓ±ol' },\r\n { value: 'en', label: 'English' },\r\n { value: 'fr', label: 'FranΓ§ais' },\r\n { value: 'it', label: 'Italiano' },\r\n { value: 'de', label: 'Deutsch' },\r\n];\r\n\r\nexport interface ConfigurationState {\r\n selectedLanguage: string;\r\n advancedHttpConfig: boolean;\r\n selectorStrategy: string;\r\n filesystemGranted: boolean;\r\n cypressFolderName: string | null;\r\n smartSelectorEnabled: boolean;\r\n startHidden: boolean;\r\n resumeTtlMinutes: number;\r\n isExporting: boolean;\r\n exportMode: ExportMode;\r\n exportTests: TestWithDetails[];\r\n exportSelectedIds: Set<number>;\r\n exportSelectedTags: Set<string>;\r\n}\r\n\r\nexport function renderExportOverlay(state: ConfigurationState, t: (key: string) => string): string {\r\n const { isExporting, exportMode, exportTests, exportSelectedIds, exportSelectedTags } = state;\r\n if (!isExporting) return '';\r\n\r\n const count = selectTestsForExport(exportTests, exportMode, {\r\n ids: exportSelectedIds,\r\n tags: exportSelectedTags,\r\n }).length;\r\n\r\n const modeBtn = (mode: ExportMode, key: string) =>\r\n `<button class=\"export-mode ${exportMode === mode ? 'active' : ''}\" data-export-mode=\"${mode}\">${t(key)}</button>`;\r\n\r\n let body: string;\r\n if (exportTests.length === 0) {\r\n body = `<div class=\"export-empty\">${t('CONFIG.EXPORT_EMPTY')}</div>`;\r\n } else if (exportMode === 'all') {\r\n body = `<div class=\"export-all-desc\">${t('CONFIG.EXPORT_ALL_DESC')}</div>`;\r\n } else if (exportMode === 'manual') {\r\n body = `<div class=\"export-list\">${exportTests.map((test) => `\r\n <label class=\"export-row\">\r\n <input type=\"checkbox\" data-export-test=\"${test.id}\" ${exportSelectedIds.has(test.id) ? 'checked' : ''} />\r\n <span class=\"export-row-name\">${escHtml(test.name)}</span>\r\n ${(test.tags ?? []).map((tag) => `<span class=\"export-row-tag\">${escHtml(tag)}</span>`).join('')}\r\n </label>`).join('')}</div>`;\r\n } else {\r\n const allTags = [...new Set(exportTests.flatMap((test) => test.tags ?? []))].sort();\r\n if (!allTags.length) {\r\n body = `<div class=\"export-empty\">${t('CONFIG.EXPORT_NO_TAGS')}</div>`;\r\n } else {\r\n const chips = `<div class=\"export-tags\">${allTags.map((tag) =>\r\n `<button class=\"export-tag ${exportSelectedTags.has(tag) ? 'active' : ''}\" data-export-tag=\"${escAttr(tag)}\">${escHtml(tag)}</button>`).join('')}</div>`;\r\n // Preview the tests that the selected tags resolve to, so QA sees exactly\r\n // what will be exported.\r\n const matched = selectTestsForExport(exportTests, 'tags', { tags: exportSelectedTags });\r\n const preview = exportSelectedTags.size === 0\r\n ? `<div class=\"export-tag-hint\">${t('CONFIG.EXPORT_TAGS_HINT')}</div>`\r\n : `<div class=\"export-result-label\">${t('CONFIG.EXPORT_RESULT_LABEL')}</div>\r\n <div class=\"export-list\">${matched.map((test) => `\r\n <div class=\"export-row export-row-static\">\r\n <span class=\"export-row-name\">${escHtml(test.name)}</span>\r\n ${(test.tags ?? []).map((tag) => `<span class=\"export-row-tag\">${escHtml(tag)}</span>`).join('')}\r\n </div>`).join('')}</div>`;\r\n body = chips + preview;\r\n }\r\n }\r\n\r\n return `\r\n <div class=\"export-overlay\" id=\"export-overlay\">\r\n <div class=\"export-modal\">\r\n <div class=\"export-hd\">${t('CONFIG.EXPORT_DIALOG_TITLE')}</div>\r\n ${exportTests.length ? `<div class=\"export-modes\">\r\n ${modeBtn('all', 'CONFIG.EXPORT_MODE_ALL')}\r\n ${modeBtn('manual', 'CONFIG.EXPORT_MODE_MANUAL')}\r\n ${modeBtn('tags', 'CONFIG.EXPORT_MODE_TAGS')}\r\n </div>` : ''}\r\n <div class=\"export-body\">${body}</div>\r\n <div class=\"export-ft\">\r\n <span class=\"export-count\">${t('CONFIG.EXPORT_COUNT')} <b>${count}</b></span>\r\n <span class=\"export-ft-actions\">\r\n <button id=\"btn-export-confirm\" class=\"btn-export-confirm\" ${count === 0 ? 'disabled' : ''}>${t('CONFIG.EXPORT_CONFIRM')}</button>\r\n <button id=\"btn-export-cancel\">${t('CONFIG.EXPORT_CANCEL')}</button>\r\n </span>\r\n </div>\r\n </div>\r\n </div>`;\r\n}\r\n\r\nexport function renderConfiguration(state: ConfigurationState, t: (key: string) => string): string {\r\n const { selectedLanguage, advancedHttpConfig, selectorStrategy, filesystemGranted, cypressFolderName, smartSelectorEnabled, startHidden, resumeTtlMinutes } = state;\r\n\r\n const langOptions = LANGS.map(\r\n (l) => `<option value=\"${l.value}\" ${selectedLanguage === l.value ? 'selected' : ''}>${l.label}</option>`,\r\n ).join('');\r\n\r\n return `\r\n <div class=\"cfg-grid\">\r\n\r\n <!-- Language -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.LANG_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.LANG_FIELD')}</span>\r\n <select id=\"lang-select\">${langOptions}</select>\r\n </div>\r\n </div>\r\n\r\n <!-- HTTP Advanced -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.HTTP_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"http-toggle\" ${advancedHttpConfig ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.HTTP_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.HTTP_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Smart Selector -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.SMART_SELECTOR_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"smart-selector-toggle\" ${smartSelectorEnabled ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.SMART_SELECTOR_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.SMART_SELECTOR_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Start Hidden -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.START_HIDDEN_SECTION')}</div>\r\n <label class=\"check-row\">\r\n <input type=\"checkbox\" id=\"start-hidden-toggle\" ${startHidden ? 'checked' : ''} />\r\n <div>\r\n <div class=\"check-title\">${t('CONFIG.START_HIDDEN_TITLE')}</div>\r\n <div class=\"check-sub\">${t('CONFIG.START_HIDDEN_SUB')}</div>\r\n </div>\r\n </label>\r\n </div>\r\n\r\n <!-- Widget position (draggable widget) -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.WIDGET_POSITION_SECTION')}</div>\r\n <div class=\"check-sub\" style=\"margin-bottom:10px\">${t('CONFIG.WIDGET_POSITION_HINT')}</div>\r\n <div class=\"btn-row\">\r\n <button id=\"btn-reset-position\">${t('CONFIG.WIDGET_POSITION_RESET_BTN')}</button>\r\n </div>\r\n </div>\r\n\r\n <!-- Recording continuity (cross-app resume TTL) -->\r\n <div class=\"card\">\r\n <div class=\"card-hd\">${t('CONFIG.RESUME_TTL_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.RESUME_TTL_LABEL')}</span>\r\n <input type=\"number\" id=\"resume-ttl-input\" min=\"1\" step=\"1\" value=\"${resumeTtlMinutes}\"\r\n style=\"width:80px;padding:5px 8px;background:#161b22;border:1px solid #30363d;border-radius:5px;color:#c9d1d9;font-size:12px;outline:none\" />\r\n </div>\r\n <div class=\"check-sub\" style=\"margin-top:8px\">${t('CONFIG.RESUME_TTL_HINT')}</div>\r\n </div>\r\n\r\n <!-- Selector Strategy -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.SELECTOR_SECTION')}</div>\r\n <div class=\"field-row\">\r\n <span class=\"field-label\">${t('CONFIG.SELECTOR_LABEL')}</span>\r\n <select id=\"selector-strategy\">\r\n <option value=\"data-cy\" ${selectorStrategy === 'data-cy' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_DATACY')}</option>\r\n <option value=\"data-testid\" ${selectorStrategy === 'data-testid' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_TESTID')}</option>\r\n <option value=\"aria-label\" ${selectorStrategy === 'aria-label' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_ARIA')}</option>\r\n <option value=\"id\" ${selectorStrategy === 'id' ? 'selected' : ''}>${t('CONFIG.SELECTOR_OPT_ID')}</option>\r\n </select>\r\n </div>\r\n <div class=\"check-sub\" style=\"margin-top:8px\">${t('CONFIG.SELECTOR_HINT')}</div>\r\n </div>\r\n\r\n <!-- Cypress Folder -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.FOLDER_SECTION')}</div>\r\n <div class=\"fs-layout\">\r\n <pre class=\"fs-tree\">cypress/ <span style=\"color:#484f58\">${t('RECORDER.FS_TREE_PICK_HINT')}</span>\r\nβββ e2e/\r\n βββ *.cy.ts</pre>\r\n <div class=\"fs-right\">\r\n <div class=\"fs-status\">\r\n <span class=\"fs-dot ${filesystemGranted ? 'on' : 'off'}\"></span>\r\n ${filesystemGranted && cypressFolderName\r\n ? `<span>${t('CONFIG.FOLDER_CONNECTED')}</span> <span class=\"fs-folder\">π ${escHtml(cypressFolderName)}</span>`\r\n : `<span>${t('CONFIG.FOLDER_NOT_SET')}</span>`}\r\n </div>\r\n <div class=\"btn-row\">\r\n <button id=\"btn-change-folder\">\r\n ${filesystemGranted ? t('CONFIG.FOLDER_CHANGE_BTN') : t('CONFIG.FOLDER_SELECT_BTN')}\r\n </button>\r\n ${filesystemGranted\r\n ? `<button id=\"btn-revoke\" class=\"btn-danger\">${t('CONFIG.FOLDER_REVOKE_BTN')}</button>`\r\n : ''}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Data -->\r\n <div class=\"card card-wide\">\r\n <div class=\"card-hd\">${t('CONFIG.DATA_SECTION')}</div>\r\n <p class=\"data-desc\">${t('CONFIG.DATA_DESC')}</p>\r\n <div class=\"btn-row\">\r\n <button id=\"btn-export\">${t('CONFIG.EXPORT_BTN')}</button>\r\n <label style=\"cursor:pointer;margin:0\">\r\n <span class=\"btn-import\">${t('CONFIG.IMPORT_BTN')}</span>\r\n <input type=\"file\" class=\"file-input\" id=\"file-input\" accept=\".json\" />\r\n </label>\r\n </div>\r\n </div>\r\n\r\n </div>${renderExportOverlay(state, t)}`;\r\n}\r\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport type { TestWithDetails } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport type { Lang } from '../../models/lang.model';\r\nimport type { SelectorStrategy } from '../../services/recording.service';\r\nimport { RESUME_TTL_CONFIG_KEY, DEFAULT_RESUME_TTL_MINUTES } from '../../models/active-session.model';\r\nimport { showToast } from '../../utils/toast.utils';\r\nimport { selectTestsForExport, type ExportMode } from '../../utils/export-selection.utils';\r\nimport { CONFIGURATION_STYLES } from './configuration.styles';\r\nimport { renderConfiguration } from './configuration.template';\r\n\r\nexport class ConfigurationElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n selectedLanguage = 'es';\r\n advancedHttpConfig = false;\r\n selectorStrategy: SelectorStrategy = 'data-cy';\r\n smartSelectorEnabled = true;\r\n startHidden = false;\r\n resumeTtlMinutes = DEFAULT_RESUME_TTL_MINUTES;\r\n isExporting = false;\r\n exportMode: ExportMode = 'all';\r\n exportTests: TestWithDetails[] = [];\r\n exportSelectedIds: Set<number> = new Set();\r\n exportSelectedTags: Set<string> = new Set();\r\n private filesystemGranted = false;\r\n private cypressFolderName: string | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n this.advancedHttpConfig = localStorage.getItem('extendedHttpCommands') === 'true';\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n this.loadConfig();\r\n this.render();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private async loadConfig(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n if (config?.['language']) {\r\n this.selectedLanguage = config['language'] as string;\r\n this.translation.setLang(this.selectedLanguage as Lang);\r\n }\r\n this.advancedHttpConfig = localStorage.getItem('extendedHttpCommands') === 'true';\r\n this.selectorStrategy = (config?.['selectorStrategy'] as SelectorStrategy) ?? 'data-cy';\r\n this.smartSelectorEnabled = config?.['smartSelectorEnabled'] !== 'false';\r\n this.startHidden = config?.['startHidden'] === 'true';\r\n // Only override when the key exists β otherwise an async load could clobber a\r\n // value just set via onResumeTtlChange (same pattern as `language`).\r\n const ttlRaw = config?.[RESUME_TTL_CONFIG_KEY];\r\n if (ttlRaw !== undefined && ttlRaw !== null) {\r\n const ttl = Number(ttlRaw);\r\n this.resumeTtlMinutes = Number.isFinite(ttl) && ttl > 0 ? ttl : DEFAULT_RESUME_TTL_MINUTES;\r\n }\r\n this.filesystemGranted = config?.['allowReadWriteFiles'] === 'true';\r\n const handle = config?.['cypressDirectoryHandle'] as FileSystemDirectoryHandle | undefined;\r\n this.cypressFolderName = handle?.name ?? null;\r\n this.render();\r\n }\r\n\r\n async onLanguageChange(lang: string): Promise<void> {\r\n this.selectedLanguage = lang;\r\n this.translation.setLang(lang as Lang);\r\n await this.persistence.setConfig({ language: lang });\r\n this.render();\r\n }\r\n\r\n onAdvancedHttpConfigChange(checked: boolean): void {\r\n this.advancedHttpConfig = checked;\r\n localStorage.setItem('extendedHttpCommands', checked ? 'true' : 'false');\r\n this.persistence.setConfig({ extendedHttpCommands: checked ? 'true' : 'false' });\r\n this.render();\r\n }\r\n\r\n async onStartHiddenChange(checked: boolean): Promise<void> {\r\n this.startHidden = checked;\r\n await this.persistence.setConfig({ startHidden: checked ? 'true' : 'false' });\r\n this.dispatchEvent(new CustomEvent('starthiddenchange', { detail: checked, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async onResumeTtlChange(minutes: number): Promise<void> {\r\n const safe = Number.isFinite(minutes) && minutes > 0 ? Math.round(minutes) : DEFAULT_RESUME_TTL_MINUTES;\r\n this.resumeTtlMinutes = safe;\r\n await this.persistence.setConfig({ [RESUME_TTL_CONFIG_KEY]: safe });\r\n this.render();\r\n }\r\n\r\n onResetWidgetPosition(): void {\r\n this.dispatchEvent(new CustomEvent('resetwidgetposition', { bubbles: true, composed: true }));\r\n showToast(this.t('CONFIG.WIDGET_POSITION_RESET_DONE'));\r\n }\r\n\r\n async onSmartSelectorChange(enabled: boolean): Promise<void> {\r\n this.smartSelectorEnabled = enabled;\r\n await this.persistence.setConfig({ smartSelectorEnabled: enabled ? 'true' : 'false' });\r\n this.dispatchEvent(new CustomEvent('smartselectorchange', { detail: enabled, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async onSelectorStrategyChange(strategy: SelectorStrategy): Promise<void> {\r\n this.selectorStrategy = strategy;\r\n await this.persistence.setConfig({ selectorStrategy: strategy });\r\n this.dispatchEvent(new CustomEvent('selectorstrategychange', { detail: strategy, bubbles: true, composed: true }));\r\n this.render();\r\n }\r\n\r\n async changeFolder(): Promise<void> {\r\n try {\r\n await this.persistence.requestDirectoryPermissions();\r\n await this.loadConfig();\r\n showToast(this.t('CONFIG.FOLDER_UPDATED_TOAST'));\r\n } catch (e: unknown) {\r\n if ((e as DOMException)?.name !== 'AbortError') {\r\n showToast(this.t('CONFIG.FOLDER_ERROR_TOAST'), false);\r\n }\r\n }\r\n }\r\n\r\n async revokeAccess(): Promise<void> {\r\n await this.persistence.setConfig({ allowReadWriteFiles: 'false', cypressDirectoryHandle: null });\r\n this.filesystemGranted = false;\r\n this.cypressFolderName = null;\r\n this.render();\r\n }\r\n\r\n private downloadTests(tests: TestWithDetails[]): void {\r\n const blob = new Blob([JSON.stringify({ tests, interceptors: [] }, null, 2)], { type: 'application/json' });\r\n const url = URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.href = url;\r\n a.download = 'e2e-cypress-export.json';\r\n a.click();\r\n URL.revokeObjectURL(url);\r\n }\r\n\r\n /** Downloads every saved test (used by the \"Todo\" mode and as a direct API). */\r\n async exportAllData(): Promise<void> {\r\n const tests = await this.persistence.getAllTests();\r\n this.downloadTests(tests);\r\n }\r\n\r\n /** Opens the export selection dialog, loading the current tests. */\r\n async openExportDialog(): Promise<void> {\r\n this.exportTests = await this.persistence.getAllTests();\r\n this.exportMode = 'all';\r\n this.exportSelectedIds = new Set();\r\n this.exportSelectedTags = new Set();\r\n this.isExporting = true;\r\n this.render();\r\n }\r\n\r\n cancelExport(): void {\r\n this.isExporting = false;\r\n this.exportSelectedIds.clear();\r\n this.exportSelectedTags.clear();\r\n this.render();\r\n }\r\n\r\n setExportMode(mode: ExportMode): void {\r\n this.exportMode = mode;\r\n this.render();\r\n }\r\n\r\n toggleExportTest(id: number): void {\r\n if (this.exportSelectedIds.has(id)) this.exportSelectedIds.delete(id);\r\n else this.exportSelectedIds.add(id);\r\n this.render();\r\n }\r\n\r\n toggleExportTag(tag: string): void {\r\n if (this.exportSelectedTags.has(tag)) this.exportSelectedTags.delete(tag);\r\n else this.exportSelectedTags.add(tag);\r\n this.render();\r\n }\r\n\r\n /** Downloads the tests resolved by the current mode + selection. No-op if empty. */\r\n confirmExport(): void {\r\n const subset = selectTestsForExport(this.exportTests, this.exportMode, {\r\n ids: this.exportSelectedIds,\r\n tags: this.exportSelectedTags,\r\n });\r\n if (!subset.length) return;\r\n this.downloadTests(subset);\r\n this.isExporting = false;\r\n this.exportSelectedIds.clear();\r\n this.exportSelectedTags.clear();\r\n this.render();\r\n }\r\n\r\n async importAllData(file: File): Promise<void> {\r\n const text = await file.text();\r\n let data: { tests: Record<string, unknown>[]; interceptors: Record<string, unknown>[] };\r\n try {\r\n data = JSON.parse(text);\r\n } catch {\r\n throw new Error(this.t('CONFIG.JSON_INVALID'));\r\n }\r\n if (!data || !Array.isArray(data.tests) || !Array.isArray(data.interceptors)) {\r\n throw new Error(this.t('CONFIG.JSON_BAD_FORMAT'));\r\n }\r\n // Merge: append the imported tests to whatever is already stored β never wipe\r\n // existing data (see docs/specs/004-merge-on-import.md).\r\n await this.persistence.ingestFileData(data.tests, data.interceptors);\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${CONFIGURATION_STYLES}</style>${renderConfiguration({\r\n selectedLanguage: this.selectedLanguage,\r\n advancedHttpConfig: this.advancedHttpConfig,\r\n selectorStrategy: this.selectorStrategy,\r\n filesystemGranted: this.filesystemGranted,\r\n cypressFolderName: this.cypressFolderName,\r\n smartSelectorEnabled: this.smartSelectorEnabled,\r\n startHidden: this.startHidden,\r\n resumeTtlMinutes: this.resumeTtlMinutes,\r\n isExporting: this.isExporting,\r\n exportMode: this.exportMode,\r\n exportTests: this.exportTests,\r\n exportSelectedIds: this.exportSelectedIds,\r\n exportSelectedTags: this.exportSelectedTags,\r\n }, this.t.bind(this))}`;\r\n ;(this.shadow.getElementById('lang-select') as HTMLSelectElement).addEventListener('change', (e) =>\r\n this.onLanguageChange((e.target as HTMLSelectElement).value),\r\n )\r\n ;(this.shadow.getElementById('http-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onAdvancedHttpConfigChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('smart-selector-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onSmartSelectorChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('start-hidden-toggle') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onStartHiddenChange((e.target as HTMLInputElement).checked),\r\n )\r\n ;(this.shadow.getElementById('resume-ttl-input') as HTMLInputElement).addEventListener('change', (e) =>\r\n this.onResumeTtlChange(Number((e.target as HTMLInputElement).value)),\r\n )\r\n ;this.shadow.getElementById('btn-reset-position')?.addEventListener('click', () => this.onResetWidgetPosition())\r\n ;(this.shadow.getElementById('selector-strategy') as HTMLSelectElement).addEventListener('change', (e) =>\r\n this.onSelectorStrategyChange((e.target as HTMLSelectElement).value as SelectorStrategy),\r\n );\r\n\r\n this.shadow.getElementById('btn-change-folder')?.addEventListener('click', () => this.changeFolder());\r\n this.shadow.getElementById('btn-revoke')?.addEventListener('click', () => this.revokeAccess());\r\n this.shadow.getElementById('btn-export')?.addEventListener('click', () => this.openExportDialog());\r\n\r\n this.shadow.getElementById('btn-export-confirm')?.addEventListener('click', () => this.confirmExport());\r\n this.shadow.getElementById('btn-export-cancel')?.addEventListener('click', () => this.cancelExport());\r\n this.shadow.querySelectorAll('[data-export-mode]').forEach((el) =>\r\n el.addEventListener('click', () => this.setExportMode((el as HTMLElement).dataset['exportMode'] as ExportMode)),\r\n );\r\n this.shadow.querySelectorAll('[data-export-test]').forEach((el) =>\r\n el.addEventListener('change', () => this.toggleExportTest(Number((el as HTMLElement).dataset['exportTest']))),\r\n );\r\n this.shadow.querySelectorAll('[data-export-tag]').forEach((el) =>\r\n el.addEventListener('click', () => this.toggleExportTag((el as HTMLElement).dataset['exportTag'] ?? '')),\r\n )\r\n ;(this.shadow.getElementById('file-input') as HTMLInputElement).addEventListener('change', async (e) => {\r\n const file = (e.target as HTMLInputElement).files?.[0];\r\n if (!file) return;\r\n try {\r\n await this.importAllData(file);\r\n alert(this.t('CONFIG.IMPORT_SUCCESS'));\r\n } catch (err: unknown) {\r\n alert((err as Error).message ?? this.t('CONFIG.IMPORT_ERROR'));\r\n }\r\n const target = e.target as HTMLInputElement | null;\r\n if (target) target.value = '';\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('e2e-configuration')) {\r\n customElements.define('e2e-configuration', ConfigurationElement);\r\n}\r\n","export const ADVANCED_TEST_EDITOR_STYLES = `\n :host { display: flex; flex-direction: column; flex: 1; min-height: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; overflow: hidden; }\n * { box-sizing: border-box; }\n .layout { display: flex; flex: 1; min-height: 0; }\n .sidebar {\n border-right: none; display: flex; flex-direction: column;\n background: #0d1117; flex-shrink: 0; min-width: 140px; max-width: 500px;\n }\n .tree-scroll {\n flex: 1; overflow-y: auto; padding: 6px 4px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .tree-scroll::-webkit-scrollbar { width: 4px; }\n .tree-scroll::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .resize-handle {\n width: 4px; background: #21262d; cursor: col-resize; flex-shrink: 0;\n transition: background 0.15s;\n }\n .resize-handle:hover, .resize-handle.dragging { background: #2f81f7; }\n .main { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #161b22; min-width: 0; }\n .no-perm {\n padding: 28px; color: #484f58; font-size: 13px; text-align: center;\n display: flex; flex-direction: column; align-items: center; gap: 12px; line-height: 1.6;\n }\n .tree-item {\n padding: 4px 6px; border-radius: 4px; cursor: pointer;\n font-size: 12px; color: #8b949e; white-space: nowrap;\n overflow: hidden; text-overflow: ellipsis;\n transition: background 0.12s, color 0.12s;\n display: flex; align-items: center; gap: 4px; user-select: none;\n }\n .tree-item:hover { background: #161b22; color: #c9d1d9; }\n .tree-item.selected { background: rgba(47,129,247,0.12); color: #2f81f7; }\n .tree-item.dir { color: #e3b341; font-weight: 600; }\n .tree-item.dir:hover { background: rgba(227,179,65,0.08); color: #f0c040; }\n .dir-arrow { font-size: 8px; color: #484f58; width: 10px; flex-shrink: 0; line-height: 1; }\n .tree-connector { display: block; width: 1px; background: #21262d; margin-left: 13px; height: 100%; }\n .content-area {\n flex: 1; padding: 12px 14px; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .content-area::-webkit-scrollbar { width: 4px; }\n .content-area::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .file-name { font-size: 11px; color: #484f58; margin-bottom: 8px; font-family: monospace; }\n pre {\n background: #0d1117; padding: 12px; border-radius: 8px;\n font-size: 11px; color: #c9d1d9; margin: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n line-height: 1.7; border: 1px solid #21262d;\n white-space: pre; overflow-x: auto; overflow-y: auto;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n pre::-webkit-scrollbar { width: 4px; height: 4px; }\n pre::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .pre-block { font-size: 10.5px; }\n .pre-icp .sh-str { color: #85e89d; }\n .sh-kw { color: #ff7b72; }\n .sh-bi { color: #d2a8ff; }\n .sh-str { color: #a5d6ff; }\n .sh-cmt { color: #8b949e; font-style: italic; }\n .sh-num { color: #79c0ff; }\n .footer {\n padding: 10px 14px; border-top: 1px solid #21262d;\n display: flex; gap: 8px; justify-content: flex-end; background: #161b22;\n }\n button {\n padding: 6px 16px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n button:disabled { opacity: 0.35; cursor: default; }\n .btn-save { background: #2f81f7; border-color: #2f81f7; color: #fff; }\n .btn-save:hover { background: #1f6feb; border-color: #1f6feb; color: #fff; }\n .btn-save:disabled { background: #21262d; border-color: #30363d; color: #8b949e; }\n .placeholder { color: #484f58; font-size: 13px; padding: 28px; text-align: center; }\n .test-notes {\n margin: 0 0 10px; padding: 8px 12px;\n background: rgba(47,129,247,0.06); border-left: 3px solid rgba(47,129,247,0.4);\n border-radius: 0 6px 6px 0; font-size: 12px; color: #8b949e;\n line-height: 1.6; white-space: pre-wrap; word-break: break-word;\n }\n .block-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }\n .btn-copy {\n padding: 3px 10px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; flex-shrink: 0;\n }\n .btn-copy:hover { background: #30363d; color: #e6edf3; }\n .sidebar-toolbar {\n display: flex; flex-wrap: wrap; gap: 4px; padding: 6px 6px 4px;\n border-bottom: 1px solid #21262d; flex-shrink: 0; background: #0d1117;\n }\n .btn-toolbar {\n flex: 1 1 calc(50% - 2px); padding: 4px 6px; border: 1px solid #30363d; border-radius: 5px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #161b22; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap; overflow: hidden;\n text-overflow: ellipsis;\n }\n .btn-toolbar.btn-full { flex: 1 1 100%; }\n .btn-toolbar:hover { background: #30363d; color: #e6edf3; }\n .btn-toolbar.btn-new { color: #3fb950; border-color: #238636; }\n .btn-toolbar.btn-new:hover { background: #238636; color: #fff; }\n .btn-toolbar.btn-new-folder { color: #d29922; border-color: #9e6a03; }\n .btn-toolbar.btn-new-folder:hover { background: #9e6a03; color: #fff; }\n .new-file-form {\n padding: 6px; border-bottom: 1px solid #21262d; display: flex; flex-direction: column; gap: 4px;\n }\n .new-file-form input {\n width: 100%; padding: 4px 7px; background: #0d1117; border: 1px solid #30363d;\n border-radius: 5px; color: #e6edf3; font-size: 11px; font-family: monospace;\n outline: none;\n }\n .new-file-form input:focus { border-color: #2f81f7; }\n .new-file-form .ext { font-size: 9px; color: #484f58; padding: 0 2px; }\n .new-file-actions { display: flex; gap: 4px; }\n .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; }\n .btn-confirm:hover { background: #2ea043; }\n .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; }\n .btn-cancel-form:hover { background: #30363d; color: #e6edf3; }\n`;\n","import { escHtml, escAttr } from '../../utils/html.utils';\nimport { syntaxHighlight } from '../../utils/syntax-highlight.utils';\nimport type { DirectoryNode, FileNode } from '../../services/advanced-test.transformation.service';\n\nexport interface AdvancedEditorState {\n e2eTree: Array<DirectoryNode | FileNode>;\n selectedFile: unknown;\n selectedFileContent: string | null;\n testItBlock: string;\n interceptorsBlock: string;\n testNotes: string;\n saveButtonEnabled: boolean;\n isCreatingFile: boolean;\n isCreatingFolder: boolean;\n collapsedDirs: Set<string>;\n sidebarWidth: number;\n}\n\nexport function renderNoPermission(needsReauth: boolean, t: (key: string) => string): string {\n const reauthBtn = needsReauth\n ? `<button id=\"btn-reauth\"\n style=\"margin-top:14px;padding:7px 16px;border:none;border-radius:6px;cursor:pointer;\n font-size:12px;font-weight:500;background:#2f81f7;color:#fff\">\n ${t('ADVANCED_EDITOR.REAUTH_BTN')}\n </button>`\n : '';\n\n return `\n <div class=\"no-perm\">\n <div>${needsReauth ? t('ADVANCED_EDITOR.PERMISSION_EXPIRED') : t('ADVANCED_EDITOR.NO_ACCESS')}</div>\n <div style=\"font-size:11px\">${needsReauth\n ? t('ADVANCED_EDITOR.PERMISSION_EXPIRED_HINT')\n : t('ADVANCED_EDITOR.NO_ACCESS_HINT')}</div>\n ${reauthBtn}\n </div>`;\n}\n\nexport function renderAdvancedEditor(state: AdvancedEditorState, t: (key: string) => string): string {\n const { e2eTree, selectedFile, selectedFileContent, testItBlock, interceptorsBlock, testNotes, saveButtonEnabled, isCreatingFile, isCreatingFolder, collapsedDirs, sidebarWidth } = state;\n\n const treeHtml = e2eTree.length\n ? renderTree(e2eTree, selectedFile, collapsedDirs)\n : `<div class=\"tree-item\" style=\"color:#6c7a99\">${t('ADVANCED_EDITOR.NO_FILES')}</div>`;\n\n const contentHtml = selectedFileContent\n ? `<div class=\"file-name\">π ${escHtml((selectedFile as { name?: string } | null)?.name ?? '')}</div>\n <pre class=\"pre-file\">${syntaxHighlight(selectedFileContent.slice(0, 6000))}${selectedFileContent.length > 6000 ? '\\n...' : ''}</pre>`\n : `<div class=\"placeholder\">${t('ADVANCED_EDITOR.SELECT_FILE')}</div>`;\n\n const notesHtml = (testItBlock && testNotes)\n ? `<p class=\"test-notes\">${escHtml(testNotes)}</p>`\n : '';\n\n const itHtml = testItBlock\n ? `<div style=\"margin-top:10px\">\n <div class=\"file-name block-header\">\n <span>${t('ADVANCED_EDITOR.IT_LABEL')}</span>\n <button id=\"btn-copy-it\" class=\"btn-copy\">${t('ADVANCED_EDITOR.COPY_IT_BTN')}</button>\n </div>\n <pre class=\"pre-block\">${syntaxHighlight(testItBlock.slice(0, 3000))}</pre>\n </div>` : '';\n\n const interceptorsHtml = interceptorsBlock\n ? `<div style=\"margin-top:10px\">\n <div class=\"file-name block-header\">\n <span>${t('ADVANCED_EDITOR.BEFORE_EACH_LABEL')}</span>\n <button id=\"btn-copy-interceptors\" class=\"btn-copy\">${t('ADVANCED_EDITOR.COPY_ICP_BTN')}</button>\n </div>\n <pre class=\"pre-block pre-icp\">${syntaxHighlight(interceptorsBlock.slice(0, 3000))}</pre>\n </div>` : '';\n\n const newFileForm = isCreatingFile\n ? `<div class=\"new-file-form\">\n <input id=\"input-new-file\" type=\"text\" placeholder=\"${escHtml(t('ADVANCED_EDITOR.NEW_FILE_PLACEHOLDER'))}\" autocomplete=\"off\" />\n <span class=\"ext\">.cy.ts</span>\n <div class=\"new-file-actions\">\n <button id=\"btn-new-file-confirm\" class=\"btn-confirm\">${t('ADVANCED_EDITOR.NEW_FILE_CONFIRM')}</button>\n <button id=\"btn-new-file-cancel\" class=\"btn-cancel-form\">${t('ADVANCED_EDITOR.NEW_FILE_CANCEL')}</button>\n </div>\n </div>`\n : '';\n\n const newFolderForm = isCreatingFolder\n ? `<div class=\"new-file-form\">\n <input id=\"input-new-folder\" type=\"text\" placeholder=\"${escHtml(t('ADVANCED_EDITOR.NEW_FOLDER_PLACEHOLDER'))}\" autocomplete=\"off\" />\n <div class=\"new-file-actions\">\n <button id=\"btn-new-folder-confirm\" class=\"btn-confirm\">${t('ADVANCED_EDITOR.NEW_FILE_CONFIRM')}</button>\n <button id=\"btn-new-folder-cancel\" class=\"btn-cancel-form\">${t('ADVANCED_EDITOR.NEW_FILE_CANCEL')}</button>\n </div>\n </div>`\n : '';\n\n const toolbar = `\n <div class=\"sidebar-toolbar\">\n <button id=\"btn-new-file\" class=\"btn-toolbar btn-new\">${t('ADVANCED_EDITOR.NEW_FILE_BTN')}</button>\n <button id=\"btn-new-folder\" class=\"btn-toolbar btn-new-folder\">${t('ADVANCED_EDITOR.NEW_FOLDER_BTN')}</button>\n <button id=\"btn-refresh\" class=\"btn-toolbar btn-full\">${t('ADVANCED_EDITOR.REFRESH_BTN')}</button>\n </div>`;\n\n return `\n <div class=\"layout\">\n <div class=\"sidebar\" style=\"width:${sidebarWidth}px\">\n ${toolbar}\n ${newFileForm}\n ${newFolderForm}\n <div class=\"tree-scroll\">${treeHtml}</div>\n </div>\n <div id=\"resize-handle\" class=\"resize-handle\"></div>\n <div class=\"main\">\n <div class=\"content-area\">${contentHtml}${notesHtml}${itHtml}${interceptorsHtml}</div>\n <div class=\"footer\">\n <button id=\"btn-save\" class=\"btn-save\"\n ${!saveButtonEnabled || !testItBlock ? 'disabled' : ''}>\n ${t('ADVANCED_EDITOR.INSERT_BTN')}\n </button>\n <button id=\"btn-edit\" ${!saveButtonEnabled ? 'disabled' : ''}>\n ${t('ADVANCED_EDITOR.EDIT_MANUAL_BTN')}\n </button>\n <button id=\"btn-close\">${t('ADVANCED_EDITOR.CLOSE_BTN')}</button>\n </div>\n </div>\n </div>`;\n}\n\nexport function renderTree(\n nodes: Array<DirectoryNode | FileNode>,\n selected: unknown,\n collapsedDirs: Set<string>,\n indent = 0,\n parentPath = '',\n): string {\n return nodes.map((n) => {\n const currentPath = parentPath ? `${parentPath}/${n.name}` : n.name;\n const isFile = n.kind === 'file';\n const pad = `padding-left:${6 + indent * 14}px`;\n\n if (!isFile) {\n const dir = n as DirectoryNode;\n const hasChildren = (dir.children?.length ?? 0) > 0;\n const isCollapsed = collapsedDirs.has(currentPath);\n const arrow = hasChildren ? (isCollapsed ? 'βΆ' : 'βΌ') : 'Β·';\n const dirHtml = `<div class=\"tree-item dir\" style=\"${pad}\" data-dir-path=\"${escAttr(currentPath)}\">\n <span class=\"dir-arrow\">${arrow}</span>π ${escHtml(n.name)}\n </div>`;\n if (!hasChildren || isCollapsed) return dirHtml;\n return dirHtml + renderTree(dir.children, selected, collapsedDirs, indent + 1, currentPath);\n }\n\n const isSel = (selected as { name?: string } | null)?.name === n.name;\n const cls = `tree-item${isSel ? ' selected' : ''}`;\n const data = JSON.stringify({ kind: n.kind, name: n.name }).replace(/\"/g, '"');\n return `<div class=\"${cls}\" style=\"${pad}\" data-file=\"${data}\">π ${escHtml(n.name)}</div>`;\n }).join('');\n}\n\nexport async function findFileHandleRecursive(\n dir: FileSystemDirectoryHandle,\n name: string,\n): Promise<FileSystemFileHandle | null> {\n for await (const entry of dir.values()) {\n if (entry.kind === 'file' && entry.name === name) return entry as FileSystemFileHandle;\n if (entry.kind === 'directory') {\n const found = await findFileHandleRecursive(entry as FileSystemDirectoryHandle, name);\n if (found) return found;\n }\n }\n return null;\n}\n","import { PersistenceService } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport { AdvancedTestTransformationService } from '../../services/advanced-test.transformation.service';\r\nimport { escapeSingleQuotes } from '../../utils/code-format.utils';\r\nimport { ADVANCED_TEST_EDITOR_STYLES } from './advanced-test-editor.styles';\r\nimport { renderNoPermission, renderAdvancedEditor, findFileHandleRecursive } from './advanced-test-editor.template';\r\nimport type { DirectoryNode, FileNode } from '../../services/advanced-test.transformation.service';\r\n\r\nexport class AdvancedTestEditorElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private readonly transformationService = new AdvancedTestTransformationService();\r\n\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n testId?: number;\r\n\r\n e2eTree: Array<DirectoryNode | FileNode> = [];\r\n selectedFile: unknown = null;\r\n saveButtonEnabled = false;\r\n selectedFileHandle: FileSystemFileHandle | null = null;\r\n selectedFileContent: string | null = null;\r\n testItBlock = '';\r\n interceptorsBlock = '';\r\n testNotes = '';\r\n isPreviewMode = false;\r\n previewFileName: string | null = null;\r\n previewFileContent: string | null = null;\r\n isCreatingFile = false;\r\n isCreatingFolder = false;\r\n collapsedDirs: Set<string> = new Set();\r\n sidebarWidth = 220;\r\n private hasPermission = false;\r\n private needsReauth = false;\r\n private _dirHandle: FileSystemDirectoryHandle | null = null;\r\n private _e2eHandle: FileSystemDirectoryHandle | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n this.init();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n private async init(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n const allowed = config?.['allowReadWriteFiles'] === 'true';\r\n\r\n if (!allowed) {\r\n this.hasPermission = false;\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n this.render();\r\n return;\r\n }\r\n\r\n const handle = config?.['cypressDirectoryHandle'] as FileSystemDirectoryHandle | null;\r\n if (!handle) {\r\n this.hasPermission = false;\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n this.render();\r\n return;\r\n }\r\n\r\n // queryPermission does NOT require a user gesture\r\n const perm = await (handle as unknown as FileSystemHandleWithPermission).queryPermission({ mode: 'readwrite' });\r\n this._dirHandle = handle;\r\n this.hasPermission = perm === 'granted';\r\n this.needsReauth = perm === 'prompt';\r\n\r\n if (this.testId !== undefined) await this.loadCypressCommandsForTest(this.testId);\r\n if (this.hasPermission) await this.getFoldersData();\r\n this.render();\r\n }\r\n\r\n async getFoldersData(): Promise<void> {\r\n if (!this.hasPermission || !this._dirHandle) return;\r\n try {\r\n for await (const entry of this._dirHandle.values()) {\r\n if (entry.kind === 'directory' && entry.name === 'e2e') {\r\n this._e2eHandle = entry as FileSystemDirectoryHandle;\r\n const tree = await this.transformationService.scanDirectory(this._e2eHandle);\r\n this.e2eTree = tree.children ?? [];\r\n this.render();\r\n return;\r\n }\r\n }\r\n } catch { /* silently skip permission errors */ }\r\n }\r\n\r\n async createNewFile(rawName: string): Promise<void> {\r\n if (!this._e2eHandle) return;\r\n const name = rawName.trim().replace(/\\.cy\\.ts$/, '');\r\n if (!name) return;\r\n const fileName = `${name}.cy.ts`;\r\n const template = `describe('${escapeSingleQuotes(name)}', () => {\\n\\n it('should ', () => {\\n\\n });\\n\\n});\\n`;\r\n try {\r\n const fileHandle = await this._e2eHandle.getFileHandle(fileName, { create: true });\r\n const writable = await fileHandle.createWritable();\r\n await writable.write(template);\r\n await writable.close();\r\n } catch { /* silently ignore if file already exists or permission denied */ }\r\n this.isCreatingFile = false;\r\n await this.getFoldersData();\r\n }\r\n\r\n async createNewFolder(rawName: string): Promise<void> {\r\n if (!this._e2eHandle) return;\r\n const name = rawName.trim().replace(/[/\\\\]/g, '');\r\n if (!name) return;\r\n try {\r\n await this._e2eHandle.getDirectoryHandle(name, { create: true });\r\n } catch { /* silently ignore if folder already exists or permission denied */ }\r\n this.isCreatingFolder = false;\r\n await this.getFoldersData();\r\n }\r\n\r\n async refreshTree(): Promise<void> {\r\n await this.getFoldersData();\r\n }\r\n\r\n async saveCommandsToFile(): Promise<void> {\r\n if (!this.selectedFileHandle || !this.selectedFileContent || !this.testItBlock) return;\r\n let content = this.selectedFileContent;\r\n if (this.interceptorsBlock) {\r\n content = this.transformationService.insertBeforeEach(content, this.interceptorsBlock);\r\n }\r\n const comment = this.testNotes ? this.transformationService.buildBlockComment(this.testNotes) + '\\n' : '';\r\n content = this.transformationService.insertItBlock(content, comment + this.testItBlock);\r\n if (!content) return;\r\n const writable = await this.selectedFileHandle.createWritable();\r\n await writable.write(content);\r\n await writable.close();\r\n this.dispatchEvent(new CustomEvent('closemodal', { bubbles: true, composed: true }));\r\n }\r\n\r\n async onFileClick(file: unknown): Promise<void> {\r\n if (!this.transformationService.isFile(file)) return;\r\n this.selectedFile = file;\r\n this.saveButtonEnabled = true;\r\n\r\n if (!this._dirHandle) return;\r\n const handle = await findFileHandleRecursive(this._dirHandle, (file as { name: string }).name);\r\n if (!handle) return;\r\n this.selectedFileHandle = handle;\r\n const fileObj = await handle.getFile();\r\n this.selectedFileContent = await fileObj.text();\r\n this.render();\r\n }\r\n\r\n markFileAsSelected(file: unknown): void {\r\n this.selectedFile = file;\r\n }\r\n\r\n async loadCypressCommandsForTest(testId: number): Promise<void> {\r\n const test = await this.persistence.getTestById(testId);\r\n if (test) {\r\n this.testItBlock = test.itBlock ?? '';\r\n this.interceptorsBlock = test.interceptorsBlock ?? '';\r\n this.testNotes = test.notes ?? '';\r\n } else {\r\n this.testItBlock = '';\r\n this.interceptorsBlock = '';\r\n this.testNotes = '';\r\n }\r\n this.render();\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n openEditManually(): void {\r\n if (!this.selectedFileHandle || !this.selectedFileContent) return;\r\n this.dispatchEvent(new CustomEvent('openfileeditor', {\r\n detail: {\r\n handle: this.selectedFileHandle,\r\n content: this.selectedFileContent,\r\n fileName: (this.selectedFile as { name?: string } | null)?.name ?? '',\r\n testId: this.testId,\r\n itBlock: this.testItBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n notes: this.testNotes,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n }\r\n\r\n toggleDir(path: string): void {\r\n if (this.collapsedDirs.has(path)) {\r\n this.collapsedDirs.delete(path);\r\n } else {\r\n this.collapsedDirs.add(path);\r\n }\r\n this.render();\r\n }\r\n\r\n private setupResizeHandle(): void {\r\n const handle = this.shadow.getElementById('resize-handle');\r\n const sidebar = this.shadow.querySelector('.sidebar') as HTMLElement | null;\r\n if (!handle || !sidebar) return;\r\n\r\n let startX = 0;\r\n let startWidth = 0;\r\n\r\n const onMouseMove = (e: MouseEvent) => {\r\n const delta = e.clientX - startX;\r\n const newWidth = Math.max(140, Math.min(500, startWidth + delta));\r\n this.sidebarWidth = newWidth;\r\n sidebar.style.width = `${newWidth}px`;\r\n };\r\n\r\n const onMouseUp = () => {\r\n document.removeEventListener('mousemove', onMouseMove);\r\n document.removeEventListener('mouseup', onMouseUp);\r\n document.body.style.cursor = '';\r\n document.body.style.userSelect = '';\r\n handle.classList.remove('dragging');\r\n };\r\n\r\n handle.addEventListener('mousedown', (e: MouseEvent) => {\r\n startX = e.clientX;\r\n startWidth = sidebar.offsetWidth;\r\n document.addEventListener('mousemove', onMouseMove);\r\n document.addEventListener('mouseup', onMouseUp);\r\n document.body.style.cursor = 'col-resize';\r\n document.body.style.userSelect = 'none';\r\n handle.classList.add('dragging');\r\n e.preventDefault();\r\n });\r\n }\r\n\r\n closePreview(): void {\r\n this.isPreviewMode = false;\r\n this.previewFileName = null;\r\n this.previewFileContent = null;\r\n if (this.testId !== undefined) {\r\n this.dispatchEvent(new CustomEvent('closemodal', { bubbles: true, composed: true }));\r\n }\r\n this.render();\r\n }\r\n\r\n private render(): void {\r\n if (!this.hasPermission) {\r\n this.shadow.innerHTML = `<style>${ADVANCED_TEST_EDITOR_STYLES}</style>${renderNoPermission(this.needsReauth, this.t.bind(this))}`;\r\n\r\n this.shadow.getElementById('btn-reauth')?.addEventListener('click', async () => {\r\n if (!this._dirHandle) return;\r\n const perm = await (this._dirHandle as unknown as FileSystemHandleWithPermission).requestPermission({ mode: 'readwrite' });\r\n if (perm === 'granted') {\r\n this.hasPermission = true;\r\n this.needsReauth = false;\r\n await this.getFoldersData();\r\n this.render();\r\n }\r\n });\r\n return;\r\n }\r\n\r\n this.shadow.innerHTML = `<style>${ADVANCED_TEST_EDITOR_STYLES}</style>${renderAdvancedEditor({\r\n e2eTree: this.e2eTree,\r\n selectedFile: this.selectedFile,\r\n selectedFileContent: this.selectedFileContent,\r\n testItBlock: this.testItBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n testNotes: this.testNotes,\r\n saveButtonEnabled: this.saveButtonEnabled,\r\n isCreatingFile: this.isCreatingFile,\r\n isCreatingFolder: this.isCreatingFolder,\r\n collapsedDirs: this.collapsedDirs,\r\n sidebarWidth: this.sidebarWidth,\r\n }, this.t.bind(this))}`;\r\n\r\n this.shadow.querySelectorAll('[data-file]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const data = (el as HTMLElement).dataset['file'];\r\n if (data) this.onFileClick(JSON.parse(data));\r\n });\r\n });\r\n this.shadow.querySelectorAll('[data-dir-path]').forEach((el) => {\r\n el.addEventListener('click', () => {\r\n const path = (el as HTMLElement).dataset['dirPath'];\r\n if (path) this.toggleDir(path);\r\n });\r\n });\r\n this.setupResizeHandle();\r\n this.shadow.getElementById('btn-save')\r\n ?.addEventListener('click', () => this.saveCommandsToFile());\r\n this.shadow.getElementById('btn-edit')\r\n ?.addEventListener('click', () => this.openEditManually());\r\n this.shadow.getElementById('btn-copy-it')\r\n ?.addEventListener('click', () => this.copyToClipboard(this.testItBlock));\r\n this.shadow.getElementById('btn-copy-interceptors')\r\n ?.addEventListener('click', () => this.copyToClipboard(this.interceptorsBlock));\r\n this.shadow.getElementById('btn-close')\r\n ?.addEventListener('click', () => this.closePreview());\r\n this.shadow.getElementById('btn-new-file')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFile = !this.isCreatingFile;\r\n this.isCreatingFolder = false;\r\n this.render();\r\n if (this.isCreatingFile) this.shadow.getElementById('input-new-file')?.focus();\r\n });\r\n this.shadow.getElementById('btn-new-folder')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFolder = !this.isCreatingFolder;\r\n this.isCreatingFile = false;\r\n this.render();\r\n if (this.isCreatingFolder) this.shadow.getElementById('input-new-folder')?.focus();\r\n });\r\n this.shadow.getElementById('btn-refresh')\r\n ?.addEventListener('click', () => this.refreshTree());\r\n this.shadow.getElementById('btn-new-file-confirm')\r\n ?.addEventListener('click', () => {\r\n const input = this.shadow.getElementById('input-new-file') as HTMLInputElement | null;\r\n this.createNewFile(input?.value ?? '');\r\n });\r\n this.shadow.getElementById('btn-new-file-cancel')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFile = false;\r\n this.render();\r\n });\r\n const input = this.shadow.getElementById('input-new-file') as HTMLInputElement | null;\r\n input?.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n this.createNewFile(input.value);\r\n } else if (e.key === 'Escape') {\r\n this.isCreatingFile = false;\r\n this.render();\r\n }\r\n });\r\n this.shadow.getElementById('btn-new-folder-confirm')\r\n ?.addEventListener('click', () => {\r\n const folderInput = this.shadow.getElementById('input-new-folder') as HTMLInputElement | null;\r\n this.createNewFolder(folderInput?.value ?? '');\r\n });\r\n this.shadow.getElementById('btn-new-folder-cancel')\r\n ?.addEventListener('click', () => {\r\n this.isCreatingFolder = false;\r\n this.render();\r\n });\r\n const folderInput = this.shadow.getElementById('input-new-folder') as HTMLInputElement | null;\r\n folderInput?.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter') {\r\n this.createNewFolder(folderInput.value);\r\n } else if (e.key === 'Escape') {\r\n this.isCreatingFolder = false;\r\n this.render();\r\n }\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('advanced-test-editor')) {\r\n customElements.define('advanced-test-editor', AdvancedTestEditorElement);\r\n}\r\n","export const FILE_PREVIEW_STYLES = `\n :host { display: block; height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #e6edf3; }\n * { box-sizing: border-box; }\n .container { display: flex; flex-direction: column; height: 100%; }\n .header {\n display: flex; align-items: center; gap: 8px;\n padding: 8px 12px; border-bottom: 1px solid #21262d;\n background: #161b22;\n }\n .file-name { flex: 1; font-size: 12px; color: #8b949e;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; }\n .body { display: flex; flex: 1; overflow: hidden; min-height: 0; }\n .editor {\n flex: 1; min-width: 0; padding: 14px;\n background: #0d1117; color: #c9d1d9; border: none; outline: none;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 12px;\n line-height: 1.7; resize: none;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .editor::-webkit-scrollbar { width: 5px; }\n .editor::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }\n .blocks-panel {\n width: 260px; flex-shrink: 0; border-left: 1px solid #21262d;\n background: #0d1117; padding: 10px 12px; overflow-y: auto;\n display: flex; flex-direction: column; gap: 10px;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .blocks-panel::-webkit-scrollbar { width: 4px; }\n .blocks-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 2px; }\n .block-section { display: flex; flex-direction: column; gap: 4px; }\n .block-row { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2px; }\n .block-label { font-size: 10px; color: #484f58; text-transform: uppercase; letter-spacing: 0.6px; font-weight: 600; }\n .btn-copy-sm {\n padding: 2px 8px; border: 1px solid #30363d; border-radius: 4px; cursor: pointer;\n font-size: 10px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.12s, color 0.12s; white-space: nowrap;\n }\n .btn-copy-sm:hover { background: #30363d; color: #e6edf3; }\n .block-pre {\n margin: 0; padding: 6px 8px; background: #161b22;\n border-radius: 5px; border: 1px solid #21262d;\n font-size: 10px; color: #c9d1d9; line-height: 1.6;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;\n max-height: 280px; overflow-y: auto; white-space: pre-wrap; word-break: break-all;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .diff-panel {\n flex: 1; overflow-y: auto; background: #0d1117; border-left: 1px solid #21262d;\n padding: 8px 0; min-width: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace; font-size: 11px;\n line-height: 1.6;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .diff-panel::-webkit-scrollbar { width: 5px; }\n .diff-panel::-webkit-scrollbar-thumb { background: #30363d; border-radius: 3px; }\n .diff-line {\n display: flex; gap: 0; white-space: pre; padding: 0 12px;\n }\n .diff-line.added { background: rgba(63,185,80,0.12); color: #3fb950; }\n .diff-line.removed { background: rgba(248,81,73,0.1); color: #f85149; }\n .diff-line.same { color: #484f58; }\n .diff-sign { width: 14px; flex-shrink: 0; user-select: none; }\n .diff-empty { color: #484f58; font-size: 12px; padding: 20px; text-align: center; }\n .footer {\n display: flex; gap: 8px; padding: 8px 12px;\n border-top: 1px solid #21262d; justify-content: flex-end;\n background: #161b22;\n }\n button {\n padding: 6px 14px; border: 1px solid #30363d; border-radius: 6px; cursor: pointer;\n font-size: 12px; font-weight: 500; background: #21262d; color: #8b949e;\n transition: background 0.15s, color 0.12s;\n }\n button:hover { background: #30363d; color: #e6edf3; }\n .btn-save { background: #3fb950; border-color: #3fb950; color: #fff; }\n .btn-save:hover { background: #2ea043; border-color: #2ea043; }\n .btn-launch { background: transparent; border-color: #e3b341; color: #e3b341; }\n .btn-launch:hover { background: rgba(227,179,65,0.1); }\n .btn-launch:disabled { opacity: 0.45; cursor: not-allowed; }\n .btn-launch:disabled:hover { background: transparent; }\n .launch-hint { font-size: 10px; color: #8b6d3b; align-self: center; }\n .btn-insert { background: transparent; border-color: #a371f7; color: #a371f7; }\n .btn-insert:hover { background: rgba(163,113,247,0.12); color: #c8a8ff; }\n .btn-diff-active { background: rgba(47,129,247,0.15); border-color: rgba(47,129,247,0.4); color: #2f81f7; }\n\n /* ββ Run result panel βββββββββββββββββββββββββββββββββββ */\n .run-result {\n border-top: 1px solid #21262d; padding: 8px 12px; background: #0d1117;\n max-height: 220px; overflow-y: auto; flex-shrink: 0;\n scrollbar-width: thin; scrollbar-color: #30363d transparent;\n }\n .run-status { font-size: 12px; font-weight: 600; }\n .run-passed .run-status { color: #3fb950; }\n .run-failed .run-status { color: #f85149; }\n .run-running .run-status { color: #e3b341; }\n .run-error .run-status { color: #f85149; }\n .run-output {\n margin: 6px 0 0; padding: 8px 10px; background: #161b22; border: 1px solid #21262d;\n border-radius: 5px; font-size: 10px; color: #c9d1d9; line-height: 1.5;\n font-family: 'Cascadia Code','Fira Code','Consolas',monospace;\n white-space: pre-wrap; word-break: break-word; max-height: 160px; overflow-y: auto;\n }\n`;\n","import { escHtml } from '../../utils/html.utils';\n\nexport type DiffEntry = { type: 'same' | 'added' | 'removed'; line: string };\n\nexport function computeDiff(original: string, modified: string): DiffEntry[] {\n const MAX_LINES = 600;\n const a = original.split('\\n').slice(0, MAX_LINES);\n const b = modified.split('\\n').slice(0, MAX_LINES);\n const m = a.length, n = b.length;\n\n const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] + 1 : Math.max(dp[i - 1][j], dp[i][j - 1]);\n }\n }\n\n const result: DiffEntry[] = [];\n let i = m, j = n;\n while (i > 0 || j > 0) {\n if (i > 0 && j > 0 && a[i - 1] === b[j - 1]) {\n result.unshift({ type: 'same', line: a[i - 1] });\n i--; j--;\n } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {\n result.unshift({ type: 'added', line: b[j - 1] });\n j--;\n } else {\n result.unshift({ type: 'removed', line: a[i - 1] });\n i--;\n }\n }\n return result;\n}\n\nexport function buildDiffHtml(original: string, current: string, t: (key: string) => string): string {\n if (original === current) return `<div class=\"diff-empty\">${t('FILE_PREVIEW.NO_CHANGES')}</div>`;\n\n const diff = computeDiff(original, current);\n if (!diff.length) return `<div class=\"diff-empty\">${t('FILE_PREVIEW.NO_CHANGES_SHORT')}</div>`;\n\n const CONTEXT = 2;\n const compressed: DiffEntry[] = [];\n let sameRun = 0;\n for (let idx = 0; idx < diff.length; idx++) {\n if (diff[idx].type === 'same') {\n sameRun++;\n if (sameRun <= CONTEXT) compressed.push(diff[idx]);\n else if (idx + 1 < diff.length && diff[idx + 1].type !== 'same') {\n if (sameRun > CONTEXT * 2) compressed.push({ type: 'same', line: 'β¦' });\n compressed.push(diff[idx]);\n }\n } else {\n sameRun = 0;\n compressed.push(diff[idx]);\n }\n }\n\n return compressed.map(({ type, line }) => {\n const sign = type === 'added' ? '+' : type === 'removed' ? 'β' : ' ';\n return `<div class=\"diff-line ${type}\"><span class=\"diff-sign\">${sign}</span><span>${escHtml(line)}</span></div>`;\n }).join('');\n}\n\nexport type RunState = 'idle' | 'running' | 'passed' | 'failed' | 'error';\n\nexport interface FilePreviewState {\n fileName: string | null;\n showDiff: boolean;\n fileContent: string | null;\n originalContent: string | null;\n currentContent: string;\n itBlock: string;\n interceptorsBlock: string;\n closeLabel: string;\n isLocal: boolean;\n runState: RunState;\n runOutput: string;\n}\n\nconst RUN_STATUS_KEY: Record<Exclude<RunState, 'idle'>, string> = {\n running: 'FILE_PREVIEW.LAUNCH_RUNNING',\n passed: 'FILE_PREVIEW.LAUNCH_PASSED',\n failed: 'FILE_PREVIEW.LAUNCH_FAILED',\n error: 'FILE_PREVIEW.LAUNCH_NO_RUNNER',\n};\n\nexport function renderFilePreview(state: FilePreviewState, t: (key: string) => string): string {\n const { fileName, showDiff, fileContent, originalContent, currentContent, itBlock, interceptorsBlock, closeLabel, isLocal, runState, runOutput } = state;\n\n const blocksPanelHtml = (itBlock || interceptorsBlock) ? `\n <div class=\"blocks-panel\">\n ${itBlock ? `\n <div class=\"block-section\">\n <div class=\"block-row\">\n <span class=\"block-label\">${t('FILE_PREVIEW.BLOCK_IT')}</span>\n <button id=\"btn-copy-it\" class=\"btn-copy-sm\">${t('FILE_PREVIEW.COPY_BTN')}</button>\n </div>\n <pre class=\"block-pre\">${escHtml(itBlock.slice(0, 2000))}</pre>\n </div>` : ''}\n ${interceptorsBlock ? `\n <div class=\"block-section\">\n <div class=\"block-row\">\n <span class=\"block-label\">${t('FILE_PREVIEW.BLOCK_BEFORE_EACH')}</span>\n <button id=\"btn-copy-icp\" class=\"btn-copy-sm\">${t('FILE_PREVIEW.COPY_BTN')}</button>\n </div>\n <pre class=\"block-pre\" style=\"color:#3fb950\">${escHtml(interceptorsBlock.slice(0, 2000))}</pre>\n </div>` : ''}\n </div>` : '';\n\n const hasChanges = originalContent !== null && originalContent !== (fileContent ?? '');\n const hasBlocks = !!(itBlock || interceptorsBlock);\n\n const launchBtnHtml = isLocal\n ? `<button id=\"btn-launch\" class=\"btn-launch\" ${runState === 'running' ? 'disabled' : ''}>${runState === 'running' ? t('FILE_PREVIEW.LAUNCH_RUNNING') : t('FILE_PREVIEW.LAUNCH_BTN')}</button>`\n : `<button class=\"btn-launch\" disabled title=\"${t('FILE_PREVIEW.LAUNCH_LOCAL_ONLY')}\">${t('FILE_PREVIEW.LAUNCH_BTN')}</button>\n <span class=\"launch-hint\">${t('FILE_PREVIEW.LAUNCH_LOCAL_ONLY')}</span>`;\n\n const runResultHtml = runState !== 'idle'\n ? `<div class=\"run-result run-${runState}\">\n <span class=\"run-status\">${t(RUN_STATUS_KEY[runState])}</span>\n ${runOutput ? `<pre class=\"run-output\">${escHtml(runOutput.slice(0, 8000))}</pre>` : ''}\n </div>`\n : '';\n\n return `\n <div class=\"container\">\n <div class=\"header\">\n <span class=\"file-name\">π ${fileName ? escHtml(fileName) : t('FILE_PREVIEW.NO_FILE')}</span>\n <button id=\"btn-copy\" title=\"${t('FILE_PREVIEW.COPY_TITLE')}\">π</button>\n </div>\n <div class=\"body\">\n ${showDiff\n ? `<div class=\"diff-panel\" id=\"diff-panel\">${buildDiffHtml(originalContent ?? '', currentContent, t)}</div>`\n : `<textarea class=\"editor\" id=\"editor\" spellcheck=\"false\">${escHtml(fileContent ?? '')}</textarea>`}\n ${blocksPanelHtml}\n </div>\n ${runResultHtml}\n <div class=\"footer\">\n ${launchBtnHtml}\n ${hasChanges ? `<button id=\"btn-diff\" class=\"${showDiff ? 'btn-diff-active' : ''}\">${t('FILE_PREVIEW.DIFF_BTN')}</button>` : ''}\n ${hasBlocks && !showDiff ? `<button id=\"btn-insert\" class=\"btn-insert\" title=\"${t('FILE_PREVIEW.INSERT_TITLE')}\">${t('FILE_PREVIEW.INSERT_BTN')}</button>` : ''}\n <button id=\"btn-save\" class=\"btn-save\">${t('FILE_PREVIEW.SAVE_BTN')}</button>\n <button id=\"btn-close\">${escHtml(closeLabel || t('FILE_PREVIEW.CLOSE_BTN'))}</button>\n </div>\n </div>`;\n}\n","import { translationService, type TranslationService } from '../../services/translation.service';\r\nimport { advancedTestTransformationService } from '../../services/advanced-test.transformation.service';\r\nimport { showToast } from '../../utils/toast.utils';\r\nimport { isLocalHost } from '../../utils/host.utils';\r\nimport { FILE_PREVIEW_STYLES } from './file-preview.styles';\r\nimport { renderFilePreview, type RunState } from './file-preview.template';\r\n\r\nexport class FilePreviewElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private textarea: HTMLTextAreaElement | null = null;\r\n\r\n fileName: string | null = null;\r\n closeLabel = '';\r\n translation: TranslationService = translationService;\r\n itBlock = '';\r\n interceptorsBlock = '';\r\n notes = '';\r\n commands: string[] = [];\r\n interceptors: string[] = [];\r\n /** Endpoint of the local Cypress runner. Configurable; defaults to the bundled runner's port. */\r\n runnerUrl = 'http://localhost:8123/run-test';\r\n /** Whether the app is served locally β gates the launch button. Overridable for tests. */\r\n isLocal = isLocalHost(window.location.hostname);\r\n private _fileContent: string | null = null;\r\n private _originalContent: string | null = null;\r\n private _showDiff = false;\r\n private _runState: RunState = 'idle';\r\n private _runOutput = '';\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if (!this.closeLabel) this.closeLabel = this.translation.translate('FILE_PREVIEW.CLOSE_BTN');\r\n this.render();\r\n }\r\n\r\n private t(key: string): string { return this.translation.translate(key); }\r\n\r\n get fileContent(): string | null { return this._fileContent; }\r\n set fileContent(v: string | null) {\r\n if (this._originalContent === null) this._originalContent = v;\r\n this._fileContent = v;\r\n if (this.textarea) this.textarea.value = v ?? '';\r\n else this.render();\r\n }\r\n\r\n saveFile(): void {\r\n const content = this.textarea?.value ?? this._fileContent ?? '';\r\n this.dispatchEvent(new CustomEvent('save', { detail: content, bubbles: true, composed: true }));\r\n }\r\n\r\n onClose(): void {\r\n this.dispatchEvent(new CustomEvent('close', { bubbles: true, composed: true }));\r\n }\r\n\r\n /**\r\n * Runs the current spec headless via the local runner and shows the result.\r\n * No-op off localhost. Never throws β connection failures surface as an\r\n * \"error\" state + toast instead of an unhandled rejection.\r\n */\r\n async launchTest(specPath?: string): Promise<void> {\r\n if (!this.isLocal) return;\r\n const path = specPath ?? this.fileName ?? '';\r\n if (!path) return;\r\n\r\n this._runState = 'running';\r\n this._runOutput = '';\r\n this.render();\r\n\r\n try {\r\n const response = await fetch(this.runnerUrl, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({ specPath: path }),\r\n });\r\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\r\n const result = await response.json() as { success?: boolean; output?: string };\r\n this._runOutput = result.output ?? '';\r\n this._runState = result.success ? 'passed' : 'failed';\r\n } catch {\r\n this._runState = 'error';\r\n this._runOutput = '';\r\n showToast(this.t('FILE_PREVIEW.LAUNCH_NO_RUNNER'), false);\r\n }\r\n this.render();\r\n }\r\n\r\n copyToClipboard(text: string): void {\r\n navigator.clipboard?.writeText(text);\r\n }\r\n\r\n toggleDiff(): void {\r\n this._showDiff = !this._showDiff;\r\n this.render();\r\n }\r\n\r\n /**\r\n * Merges the it() and beforeEach() blocks into the current editor content\r\n * using the same logic as the automatic \"Insert into file\" action, so the\r\n * user does not have to copy/paste manually. Leaves the content untouched\r\n * (and warns) when the file has no valid describe() block to insert into.\r\n */\r\n insertBlocks(): void {\r\n const base = this.textarea?.value ?? this._fileContent ?? '';\r\n let content = base;\r\n if (this.interceptorsBlock) {\r\n const merged = advancedTestTransformationService.insertBeforeEach(content, this.interceptorsBlock);\r\n if (merged) content = merged;\r\n }\r\n if (this.itBlock) {\r\n const comment = this.notes ? advancedTestTransformationService.buildBlockComment(this.notes) + '\\n' : '';\r\n const merged = advancedTestTransformationService.insertItBlock(content, comment + this.itBlock);\r\n if (merged) content = merged;\r\n }\r\n if (content === base) {\r\n showToast(this.t('FILE_PREVIEW.INSERT_ERROR'), false);\r\n return;\r\n }\r\n this._fileContent = content;\r\n this.render();\r\n showToast(this.t('FILE_PREVIEW.INSERT_DONE'));\r\n }\r\n\r\n private render(): void {\r\n this.shadow.innerHTML = `<style>${FILE_PREVIEW_STYLES}</style>${renderFilePreview({\r\n fileName: this.fileName,\r\n showDiff: this._showDiff,\r\n fileContent: this._fileContent,\r\n originalContent: this._originalContent,\r\n currentContent: this.textarea?.value ?? this._fileContent ?? '',\r\n itBlock: this.itBlock,\r\n interceptorsBlock: this.interceptorsBlock,\r\n closeLabel: this.closeLabel,\r\n isLocal: this.isLocal,\r\n runState: this._runState,\r\n runOutput: this._runOutput,\r\n }, this.t.bind(this))}`;\r\n\r\n this.textarea = this.shadow.getElementById('editor') as HTMLTextAreaElement | null;\r\n if (this.textarea) {\r\n const ta = this.textarea;\r\n this.textarea.addEventListener('input', () => {\r\n this._fileContent = ta.value;\r\n });\r\n }\r\n this.shadow.getElementById('btn-save')?.addEventListener('click', () => this.saveFile());\r\n this.shadow.getElementById('btn-close')?.addEventListener('click', () => this.onClose());\r\n this.shadow.getElementById('btn-launch')?.addEventListener('click', () => this.launchTest());\r\n this.shadow.getElementById('btn-copy')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.textarea?.value ?? this._fileContent ?? '');\r\n });\r\n this.shadow.getElementById('btn-diff')?.addEventListener('click', () => this.toggleDiff());\r\n this.shadow.getElementById('btn-insert')?.addEventListener('click', () => this.insertBlocks());\r\n this.shadow.getElementById('btn-copy-it')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.itBlock);\r\n });\r\n this.shadow.getElementById('btn-copy-icp')?.addEventListener('click', () => {\r\n this.copyToClipboard(this.interceptorsBlock);\r\n });\r\n }\r\n}\r\n\r\nif (!customElements.get('file-preview')) {\r\n customElements.define('file-preview', FilePreviewElement);\r\n}\r\n","import Swal from 'sweetalert2';\r\nimport { getRecorderStyles } from './lib-e2e-recorder.styles';\r\nimport { renderRecorderWidget } from './lib-e2e-recorder.template';\r\nimport { RecordingService, type SelectorStrategy } from '../../services/recording.service';\r\nimport { PersistenceService } from '../../services/persistence.service';\r\nimport { TranslationService } from '../../services/translation.service';\r\nimport { HttpMonitor } from '../../services/http-monitor';\r\nimport {\r\n injectStyles,\r\n LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES,\r\n SCROLLBAR_STYLES,\r\n} from '../../utils/styles.utils';\r\nimport {\r\n makeModalResizable,\r\n makeSwalDraggable,\r\n setSwal2DataCyAttribute,\r\n} from '../../utils/modal.utils';\r\nimport type { Lang } from '../../models/lang.model';\r\nimport {\r\n type ActiveSessionState,\r\n ACTIVE_SESSION_BREADCRUMB_KEY,\r\n RESUME_TTL_CONFIG_KEY,\r\n DEFAULT_RESUME_TTL_MINUTES,\r\n} from '../../models/active-session.model';\r\nimport {\r\n type ExpandDirection,\r\n type Point,\r\n DRAG_THRESHOLD,\r\n clampTogglePosition,\r\n resolveExpandDirection,\r\n defaultTogglePosition,\r\n boxTopLeftFor,\r\n} from '../../utils/widget-position.utils';\r\nimport { showToast } from '../../utils/toast.utils';\r\n\r\n/**\r\n * Minimal property/event shapes for dynamically-created child custom elements.\r\n * Not extending HTMLElement avoids conflicts with the strict EventListener signature;\r\n * cast to Node/HTMLElement only for actual DOM insertion.\r\n */\r\ninterface PrevisualizerEl {\r\n translation: TranslationService; commands: string[]; interceptors: string[]; editable: boolean;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface TestEditorEl { persistence: PersistenceService; translation: TranslationService }\r\ninterface SaveTestEl {\r\n translation: TranslationService;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface ConfigEl {\r\n persistence: PersistenceService; translation: TranslationService;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void): void;\r\n}\r\ninterface AdvancedEditorEl {\r\n persistence: PersistenceService; translation: TranslationService; testId?: number;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void | Promise<void>): void;\r\n}\r\ninterface FilePreviewEl {\r\n translation: TranslationService; fileContent: string | null; fileName: string | null;\r\n closeLabel: string; itBlock: string; interceptorsBlock: string; notes: string;\r\n addEventListener(type: string, listener: (e: CustomEvent) => void | Promise<void>): void;\r\n}\r\ninterface SelectorPickerEl {\r\n targetElement: HTMLElement; recording: RecordingService; translation: TranslationService;\r\n}\r\n\r\nexport class LibE2eRecorderElement extends HTMLElement {\r\n private shadow: ShadowRoot;\r\n private _isDisabled = false;\r\n private keydownHandler!: (e: KeyboardEvent) => void;\r\n private recordingUnsub?: () => void;\r\n private commandsUnsub?: () => void;\r\n private interceptorsUnsub?: () => void;\r\n private pauseUnsub?: () => void;\r\n private selectorNotFoundUnsub?: () => void;\r\n private langUnsub?: () => void;\r\n private sessionUnsub?: () => void;\r\n private sessionSaveTimer?: ReturnType<typeof setTimeout>;\r\n private controlFirstTimeData = true;\r\n\r\n // ββ draggable widget (spec 007) ββ\r\n private togglePos: Point | null = null;\r\n private expandDir: ExpandDirection = 'up-left';\r\n private dragState?: { startX: number; startY: number; origX: number; origY: number; moved: boolean };\r\n private suppressNextToggleClick = false;\r\n private widgetPointerMove?: (e: MouseEvent) => void;\r\n private widgetPointerUp?: () => void;\r\n private widgetResize?: () => void;\r\n private _previsualizerRef: { commands: string[]; interceptors: string[] } | null = null;\r\n private httpMonitor?: HttpMonitor;\r\n private smartSelectorEnabled = true;\r\n\r\n recording!: RecordingService;\r\n persistence!: PersistenceService;\r\n translation!: TranslationService;\r\n\r\n isVisible = false;\r\n isRecording = false;\r\n isPaused = false;\r\n cypressCommands: string[] = [];\r\n interceptors: string[] = [];\r\n\r\n isCommandsDialogOpen = false;\r\n isSavedTestsDialogOpen = false;\r\n isSaveTestDialogOpen = false;\r\n isSettingsDialogOpen = false;\r\n isAdvancedEditorDialogOpen = false;\r\n\r\n constructor() {\r\n super();\r\n this.shadow = this.attachShadow({ mode: 'open' });\r\n }\r\n\r\n connectedCallback(): void {\r\n if ('Cypress' in window) {\r\n this._isDisabled = true;\r\n return;\r\n }\r\n if (!this.getAttribute('data-cy')) {\r\n this.setAttribute('data-cy', 'lib-e2e-cypress-for-dummys');\r\n }\r\n if (!this.recording) this.recording = new RecordingService();\r\n if (!this.persistence) this.persistence = new PersistenceService();\r\n if (!this.translation) this.translation = new TranslationService();\r\n\r\n this.httpMonitor = new HttpMonitor(this.recording);\r\n this.httpMonitor.install();\r\n\r\n injectStyles(LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES, 'lib-e2e-swal2-styles');\r\n injectStyles(SCROLLBAR_STYLES, 'lib-e2e-scrollbar-styles');\r\n\r\n this.initHttpConfig();\r\n this.initLanguage();\r\n this.initFilesystemAccess();\r\n this.initSelectorStrategy();\r\n this.initSubscriptions();\r\n this.render();\r\n this.initVisibility();\r\n this.initSessionContinuity();\r\n this.initWidgetPosition();\r\n\r\n this.keydownHandler = (e: KeyboardEvent) => this.handleKeyboardEvent(e);\r\n window.addEventListener('keydown', this.keydownHandler);\r\n\r\n // Draggable widget (spec 007): pointer move/up tracked at window level so the\r\n // drag keeps working even if the cursor leaves the toggle button.\r\n this.widgetPointerMove = (e: MouseEvent) => this.onWidgetPointerMove(e);\r\n this.widgetPointerUp = () => this.onWidgetPointerUp();\r\n this.widgetResize = () => this.applyWidgetPosition();\r\n window.addEventListener('pointermove', this.widgetPointerMove as EventListener);\r\n window.addEventListener('pointerup', this.widgetPointerUp);\r\n window.addEventListener('resize', this.widgetResize);\r\n }\r\n\r\n disconnectedCallback(): void {\r\n if (this._isDisabled) return;\r\n window.removeEventListener('keydown', this.keydownHandler);\r\n // Final flush: if a recording is in progress, persist it synchronously-ish\r\n // before tearing the service down, so an unmount (single-spa per-sub-project\r\n // placement) does not lose the last commands. The realm survives client-side\r\n // navigation, so this async write completes even after the element is gone.\r\n this.flushActiveSessionOnDisconnect();\r\n this.recordingUnsub?.();\r\n this.commandsUnsub?.();\r\n this.interceptorsUnsub?.();\r\n this.pauseUnsub?.();\r\n this.selectorNotFoundUnsub?.();\r\n this.langUnsub?.();\r\n this.sessionUnsub?.();\r\n if (this.widgetPointerMove) window.removeEventListener('pointermove', this.widgetPointerMove as EventListener);\r\n if (this.widgetPointerUp) window.removeEventListener('pointerup', this.widgetPointerUp);\r\n if (this.widgetResize) window.removeEventListener('resize', this.widgetResize);\r\n this.httpMonitor?.uninstall();\r\n this.recording.destroy();\r\n }\r\n\r\n private async initHttpConfig(): Promise<void> {\r\n const config = await this.persistence.getConfig('extendedHttpCommands');\r\n if (config === null) {\r\n await this.persistence.setConfig({ extendedHttpCommands: 'true' });\r\n localStorage.setItem('extendedHttpCommands', 'true');\r\n } else {\r\n localStorage.setItem('extendedHttpCommands', (config['extendedHttpCommands'] as string) ?? 'true');\r\n }\r\n }\r\n\r\n private async initLanguage(): Promise<void> {\r\n const config = await this.persistence.getConfig('language');\r\n const lang = config?.['language'] as Lang | undefined;\r\n this.translation.setLang(lang ?? this.translation.detectLang());\r\n }\r\n\r\n private initSubscriptions(): void {\r\n this.recordingUnsub = this.recording.onRecordingChange((val) => {\r\n this.isRecording = val;\r\n if (!val && !this.controlFirstTimeData) {\r\n this.saveRecordingHistory();\r\n // Stopping the recording ends the cross-app session: only an actively\r\n // recording session is ever persisted/resumed (spec 006, Q2).\r\n this.clearSessionPersistence();\r\n this.showSaveTestDialog();\r\n }\r\n this.controlFirstTimeData = false;\r\n this.render();\r\n });\r\n // Persist the live session incrementally so it survives a micro-frontend\r\n // crossing or a same-origin reload (spec 006).\r\n this.sessionUnsub = this.recording.onSessionChange((state) => this.persistActiveSession(state));\r\n this.commandsUnsub = this.recording.onCommandsChange((cmds) => {\r\n this.cypressCommands = cmds;\r\n if (this._previsualizerRef) this._previsualizerRef.commands = cmds;\r\n });\r\n this.interceptorsUnsub = this.recording.onInterceptorsChange((icps) => {\r\n this.interceptors = icps;\r\n if (this._previsualizerRef) this._previsualizerRef.interceptors = icps;\r\n });\r\n this.pauseUnsub = this.recording.onPauseChange((paused) => {\r\n this.isPaused = paused;\r\n this.render();\r\n });\r\n this.selectorNotFoundUnsub = this.recording.onSelectorNotFound((target) => {\r\n if (this.smartSelectorEnabled) this.showSelectorPicker(target);\r\n });\r\n // Re-render the widget chrome when the UI language changes so labels update live.\r\n this.langUnsub = this.translation.onLangChange(() => this.render());\r\n }\r\n\r\n private showSelectorPicker(target: HTMLElement): void {\r\n import('../../components/selector-picker/selector-picker').then(() => {\r\n const existing = document.querySelector('selector-picker');\r\n if (existing) existing.remove();\r\n\r\n const picker = document.createElement('selector-picker') as unknown as SelectorPickerEl;\r\n picker.targetElement = target;\r\n picker.recording = this.recording;\r\n picker.translation = this.translation;\r\n document.body.appendChild(picker as unknown as Node);\r\n });\r\n }\r\n\r\n private async initVisibility(): Promise<void> {\r\n if (this.hasAttribute('start-hidden')) {\r\n // Attribute overrides DB: presence β hidden, explicit \"false\" β visible\r\n this.isVisible = this.getAttribute('start-hidden') === 'false';\r\n this.style.display = this.isVisible ? '' : 'none';\r\n return;\r\n }\r\n const config = await this.persistence.getGeneralConfig();\r\n this.isVisible = config?.['startHidden'] !== 'true';\r\n this.style.display = this.isVisible ? '' : 'none';\r\n }\r\n\r\n private async initSelectorStrategy(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n const strategy = config?.['selectorStrategy'] as string | undefined;\r\n if (strategy) this.recording.selectorStrategy = strategy as SelectorStrategy;\r\n this.smartSelectorEnabled = config?.['smartSelectorEnabled'] !== 'false';\r\n }\r\n\r\n // ββ cross-app session continuity (spec 006) βββββββββββββββββββββββββββββββ\r\n\r\n /**\r\n * On mount, detect a persisted live recording session and either resume it\r\n * silently (recent) or prompt continue/discard (stale). No-op when there is\r\n * no actively-recording session.\r\n */\r\n private async initSessionContinuity(): Promise<void> {\r\n if (this._isDisabled) return;\r\n const session = await this.persistence.getActiveSession();\r\n if (!session || !session.isRecording) return;\r\n const ttlMin = await this.getResumeTtlMinutes();\r\n const ageMs = Date.now() - session.updatedAt;\r\n if (ageMs <= ttlMin * 60_000) {\r\n this.resumeSessionState(session);\r\n } else {\r\n this.promptResumeOrDiscard(session);\r\n }\r\n }\r\n\r\n private async getResumeTtlMinutes(): Promise<number> {\r\n const config = await this.persistence.getConfig(RESUME_TTL_CONFIG_KEY);\r\n const raw = config?.[RESUME_TTL_CONFIG_KEY];\r\n const n = typeof raw === 'number' ? raw : Number(raw);\r\n return Number.isFinite(n) && n > 0 ? n : DEFAULT_RESUME_TTL_MINUTES;\r\n }\r\n\r\n /** Rehydrates the recorder from a persisted session (no bootstrap re-emitted). */\r\n private resumeSessionState(session: ActiveSessionState): void {\r\n this.recording.restoreSession(session);\r\n this.cypressCommands = session.commands;\r\n this.interceptors = session.interceptors;\r\n this.controlFirstTimeData = false;\r\n this.render();\r\n }\r\n\r\n private async promptResumeOrDiscard(session: ActiveSessionState): Promise<void> {\r\n const t = this.translation.translate.bind(this.translation);\r\n const result = await Swal.fire({\r\n title: t('RECORDER.SESSION_RESUME_TITLE'),\r\n html:\r\n `<div style=\"padding:8px 4px;color:#8b949e;font-size:13px;line-height:1.6\">` +\r\n `<p>${t('RECORDER.SESSION_RESUME_TEXT')}</p>` +\r\n `<p style=\"margin-top:6px;color:#c9d1d9\"><b>${session.commands.length}</b> ${t('RECORDER.SESSION_RESUME_COUNT')}</p>` +\r\n `</div>`,\r\n showCancelButton: true,\r\n confirmButtonText: t('RECORDER.SESSION_CONTINUE_BTN'),\r\n cancelButtonText: t('RECORDER.SESSION_DISCARD_BTN'),\r\n color: '#e6edf3',\r\n });\r\n if (result && (result as { isConfirmed?: boolean }).isConfirmed) {\r\n this.resumeSessionState(session);\r\n } else {\r\n this.discardSession();\r\n }\r\n }\r\n\r\n /** Debounced persistence of the live session; clears it the moment recording stops. */\r\n private persistActiveSession(state: ActiveSessionState): void {\r\n if (this._isDisabled) return;\r\n if (!state.isRecording) {\r\n this.clearSessionPersistence();\r\n return;\r\n }\r\n this.writeSessionBreadcrumb(state);\r\n if (this.sessionSaveTimer) clearTimeout(this.sessionSaveTimer);\r\n this.sessionSaveTimer = setTimeout(() => {\r\n const snap = this.recording.getSessionSnapshot();\r\n if (snap.isRecording) this.persistence.saveActiveSession(snap).catch(() => { /* storage errors are non-fatal */ });\r\n }, 300);\r\n }\r\n\r\n private writeSessionBreadcrumb(state: ActiveSessionState): void {\r\n try {\r\n localStorage.setItem(ACTIVE_SESSION_BREADCRUMB_KEY, JSON.stringify({\r\n sessionId: state.sessionId,\r\n isRecording: state.isRecording,\r\n updatedAt: state.updatedAt,\r\n }));\r\n } catch { /* ignore storage errors */ }\r\n }\r\n\r\n private flushActiveSessionOnDisconnect(): void {\r\n const snap = this.recording.getSessionSnapshot();\r\n if (!snap.isRecording) return;\r\n if (this.sessionSaveTimer) clearTimeout(this.sessionSaveTimer);\r\n this.writeSessionBreadcrumb(snap);\r\n this.persistence.saveActiveSession(snap).catch(() => { /* non-fatal */ });\r\n }\r\n\r\n private clearSessionPersistence(): void {\r\n if (this.sessionSaveTimer) { clearTimeout(this.sessionSaveTimer); this.sessionSaveTimer = undefined; }\r\n try { localStorage.removeItem(ACTIVE_SESSION_BREADCRUMB_KEY); } catch { /* ignore */ }\r\n this.persistence.clearActiveSession().catch(() => { /* non-fatal */ });\r\n }\r\n\r\n /** True when a synchronous breadcrumb marks an active recording session. */\r\n hasActiveSession(): boolean {\r\n try {\r\n const raw = localStorage.getItem(ACTIVE_SESSION_BREADCRUMB_KEY);\r\n if (!raw) return false;\r\n return !!(JSON.parse(raw) as { isRecording?: boolean }).isRecording;\r\n } catch { return false; }\r\n }\r\n\r\n /** Programmatically resume the persisted session, if any. */\r\n resumeSession(): void {\r\n this.persistence.getActiveSession().then((s) => { if (s) this.resumeSessionState(s); });\r\n }\r\n\r\n /** Discard the persisted live session (breadcrumb + DB record). */\r\n discardSession(): void {\r\n this.clearSessionPersistence();\r\n }\r\n\r\n // ββ draggable widget (spec 007) ββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n /** Loads a previously saved widget position and applies it. */\r\n private async initWidgetPosition(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n const pos = config?.['widgetPosition'] as Partial<Point> | null | undefined;\r\n if (pos && typeof pos.x === 'number' && typeof pos.y === 'number') {\r\n this.togglePos = { x: pos.x, y: pos.y };\r\n }\r\n this.applyWidgetPosition();\r\n }\r\n\r\n /** Positions the `.widget` box from the (clamped) toggle centre and orients the arc. */\r\n private applyWidgetPosition(): void {\r\n const widget = this.shadow.querySelector('.widget') as HTMLElement | null;\r\n if (!widget) return;\r\n const vw = window.innerWidth;\r\n const vh = window.innerHeight;\r\n const centre = this.togglePos ?? defaultTogglePosition(vw, vh);\r\n const clamped = clampTogglePosition(centre.x, centre.y, vw, vh);\r\n this.expandDir = resolveExpandDirection(clamped.x, clamped.y, vw, vh);\r\n const topLeft = boxTopLeftFor(clamped, this.expandDir);\r\n widget.style.left = `${topLeft.x}px`;\r\n widget.style.top = `${topLeft.y}px`;\r\n widget.style.right = 'auto';\r\n widget.style.bottom = 'auto';\r\n widget.setAttribute('data-expand', this.expandDir);\r\n }\r\n\r\n private beginWidgetDrag(e: MouseEvent): void {\r\n const origin = this.togglePos ?? defaultTogglePosition(window.innerWidth, window.innerHeight);\r\n this.dragState = { startX: e.clientX, startY: e.clientY, origX: origin.x, origY: origin.y, moved: false };\r\n }\r\n\r\n private onWidgetPointerMove(e: MouseEvent): void {\r\n if (!this.dragState) return;\r\n const dx = e.clientX - this.dragState.startX;\r\n const dy = e.clientY - this.dragState.startY;\r\n if (!this.dragState.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\r\n this.dragState.moved = true;\r\n this.togglePos = { x: this.dragState.origX + dx, y: this.dragState.origY + dy };\r\n this.applyWidgetPosition();\r\n }\r\n\r\n private onWidgetPointerUp(): void {\r\n if (!this.dragState) return;\r\n const moved = this.dragState.moved;\r\n this.dragState = undefined;\r\n if (!moved || !this.togglePos) return;\r\n // It was a drag, not a click: suppress the click that fires next and persist.\r\n this.suppressNextToggleClick = true;\r\n const clamped = clampTogglePosition(this.togglePos.x, this.togglePos.y, window.innerWidth, window.innerHeight);\r\n this.togglePos = clamped;\r\n this.persistence.setConfig({ widgetPosition: clamped }).catch(() => { /* non-fatal */ });\r\n }\r\n\r\n /** Resets the widget to its default corner and clears the saved position. */\r\n resetWidgetPosition(): void {\r\n this.togglePos = null;\r\n this.persistence.setConfig({ widgetPosition: null }).catch(() => { /* non-fatal */ });\r\n this.applyWidgetPosition();\r\n }\r\n\r\n toggle(): void {\r\n this.recording.toggleRecording();\r\n }\r\n\r\n togglePause(): void {\r\n this.recording.togglePause();\r\n }\r\n\r\n setLanguage(lang?: string): void {\r\n const resolved = lang ? (lang as Lang) : this.translation.detectLang();\r\n this.translation.setLang(resolved);\r\n }\r\n\r\n handleKeyboardEvent(event: KeyboardEvent): void {\r\n if (!event.ctrlKey) return;\r\n const key = event.key.toLowerCase();\r\n if (key === 'e' && event.shiftKey) { event.preventDefault(); this.toggleVisibility(); return; }\r\n if (!this.isVisible) return;\r\n if (key === 'r') { event.preventDefault(); this.toggle(); }\r\n else if (key === 'p') { event.preventDefault(); this.togglePause(); }\r\n else if (key === '1') { event.preventDefault(); this.showSavedTestsDialog(); }\r\n else if (key === '2') { event.preventDefault(); this.showCommandsDialog(); }\r\n else if (key === '3') { event.preventDefault(); this.showSettingsDialog(); }\r\n }\r\n\r\n toggleVisibility(): void {\r\n this.isVisible = !this.isVisible;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n }\r\n\r\n // ββ recording history (task 5) ββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private saveRecordingHistory(): void {\r\n if (!this.cypressCommands.length) return;\r\n try {\r\n const existing = JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n existing.unshift({ commands: this.cypressCommands, interceptors: this.interceptors, savedAt: Date.now() });\r\n if (existing.length > 5) existing.splice(5);\r\n localStorage.setItem('e2e-recording-history', JSON.stringify(existing));\r\n } catch { /* ignore storage errors */ }\r\n }\r\n\r\n recoverLastRecording(): void {\r\n try {\r\n const existing = JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n if (!existing.length) return;\r\n const { commands, interceptors } = existing[0];\r\n commands.forEach((cmd: string) => this.recording.appendCommand(cmd));\r\n (interceptors as string[]).forEach((_icp: string) => { /* interceptors are not appendable the same way */ });\r\n } catch { /* ignore */ }\r\n }\r\n\r\n clearRecordingHistory(): void {\r\n localStorage.removeItem('e2e-recording-history');\r\n }\r\n\r\n getRecordingHistory(): Array<{ commands: string[]; interceptors: string[]; savedAt: number }> {\r\n try {\r\n return JSON.parse(localStorage.getItem('e2e-recording-history') ?? '[]');\r\n } catch { return []; }\r\n }\r\n\r\n // ββ filesystem setup βββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private async initFilesystemAccess(): Promise<void> {\r\n const config = await this.persistence.getGeneralConfig();\r\n // Only show if the user has never made a choice (key doesn't exist yet)\r\n if (config && 'allowReadWriteFiles' in config) return;\r\n this.showFilesystemSetupDialog();\r\n }\r\n\r\n private showFilesystemSetupDialog(): void {\r\n Swal.fire({\r\n title: this.translation.translate('RECORDER.FS_TITLE'),\r\n html: '<div id=\"fs-setup-content\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('fs-setup-content');\r\n if (!container) return;\r\n container.innerHTML = `\r\n <div style=\"padding:16px 20px 20px;color:#8b949e;font-size:13px;line-height:1.7\">\r\n <p>${this.translation.translate('RECORDER.FS_INTRO_HTML')}</p>\r\n <p style=\"margin-top:10px;margin-bottom:6px;font-size:11px;color:#8b949e\">\r\n ${this.translation.translate('RECORDER.FS_STRUCTURE_HINT_HTML')}\r\n </p>\r\n <pre style=\"margin:0;padding:10px 14px;background:#0d1117;border:1px solid #21262d;\r\n border-radius:8px;font-size:11px;color:#c9d1d9;line-height:1.8;\r\n font-family:'Cascadia Code','Fira Code','Consolas',monospace\">\r\ncypress/ <span style=\"color:#484f58\">${this.translation.translate('RECORDER.FS_TREE_PICK_HINT')}</span>\r\nβββ e2e/ <span style=\"color:#484f58\">${this.translation.translate('RECORDER.FS_TREE_READ_HINT')}</span>\r\n βββ *.cy.ts</pre>\r\n <p style=\"margin-top:8px;font-size:11px;color:#484f58\">\r\n ${this.translation.translate('RECORDER.FS_PERMISSION_NOTE')}\r\n </p>\r\n <div style=\"display:flex;gap:8px;justify-content:flex-end;margin-top:20px\">\r\n <button id=\"fs-skip\"\r\n style=\"padding:7px 16px;border:1px solid #30363d;border-radius:6px;cursor:pointer;\r\n font-size:12px;font-weight:500;background:transparent;color:#8b949e\">\r\n ${this.translation.translate('RECORDER.FS_LATER_BTN')}\r\n </button>\r\n <button id=\"fs-select\"\r\n style=\"padding:7px 16px;border:none;border-radius:6px;cursor:pointer;\r\n font-size:12px;font-weight:500;background:#2f81f7;color:#fff\">\r\n ${this.translation.translate('RECORDER.FS_SELECT_BTN')}\r\n </button>\r\n </div>\r\n </div>`;\r\n\r\n document.getElementById('fs-skip')?.addEventListener('click', async () => {\r\n await this.persistence.setConfigKey('allowReadWriteFiles', 'false');\r\n Swal.close();\r\n });\r\n\r\n document.getElementById('fs-select')?.addEventListener('click', async () => {\r\n try {\r\n await this.persistence.requestDirectoryPermissions();\r\n Swal.close();\r\n showToast(this.translation.translate('RECORDER.FS_SUCCESS_TOAST'));\r\n } catch (e: unknown) {\r\n if ((e as DOMException)?.name !== 'AbortError') {\r\n showToast(this.translation.translate('RECORDER.FS_ERROR_TOAST'), false);\r\n }\r\n // AbortError = user cancelled the picker, leave dialog open\r\n }\r\n });\r\n },\r\n });\r\n }\r\n\r\n // ββ dialogs ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n showCommandsDialog(): void {\r\n this.toggleModal('isCommandsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_COMMANDS'),\r\n html: '<div id=\"commands-modal-content\" style=\"min-height:250px;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n backdrop: false,\r\n width: 640,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n // Make the container click-through so the page underneath remains interactive\r\n const swalContainer = document.querySelector('.swal2-container') as HTMLElement | null;\r\n if (swalContainer) {\r\n swalContainer.style.pointerEvents = 'none';\r\n const popup = swalContainer.querySelector('.swal2-popup') as HTMLElement | null;\r\n if (popup) popup.style.pointerEvents = 'all';\r\n }\r\n const container = document.getElementById('commands-modal-content');\r\n if (!container) return;\r\n\r\n const child = document.createElement('test-previsualizer') as unknown as PrevisualizerEl;\r\n child.translation = this.translation;\r\n child.commands = this.cypressCommands;\r\n child.interceptors = this.interceptors;\r\n child.editable = true;\r\n container.appendChild(child as unknown as Node);\r\n this._previsualizerRef = child;\r\n\r\n child.addEventListener('deletecommand', (e: CustomEvent) => {\r\n this.recording.removeCommand(e.detail);\r\n });\r\n child.addEventListener('movecommand', (e: CustomEvent) => {\r\n this.recording.moveCommand(e.detail.from, e.detail.to);\r\n });\r\n child.addEventListener('deleteinterceptor', (e: CustomEvent) => {\r\n this.recording.removeInterceptor(e.detail);\r\n });\r\n\r\n // ββ Assertion builder panel ββββββββββββββββββββββββββββββββββββββ\r\n const assertionHtml = `\r\n <div id=\"assertion-builder\"\r\n style=\"padding:10px 12px;border-top:1px solid #21262d;background:#0d1117\">\r\n <div style=\"font-size:10px;color:#484f58;text-transform:uppercase;letter-spacing:.8px;font-weight:600;margin-bottom:8px\">\r\n ${this.translation.translate('RECORDER.ASSERTION_SECTION')}\r\n </div>\r\n <div style=\"display:flex;gap:6px;flex-wrap:wrap;align-items:flex-end\">\r\n <input id=\"assert-selector\" type=\"text\"\r\n placeholder=\"${this.translation.translate('RECORDER.ASSERT_SELECTOR_PH').replace(/\"/g, '"')}\"\r\n style=\"flex:2;min-width:140px;padding:5px 8px;background:#161b22;border:1px solid #30363d;\r\n border-radius:5px;color:#c9d1d9;font-size:11px;outline:none;\r\n font-family:'Cascadia Code','Fira Code',monospace\"/>\r\n <select id=\"assert-type\"\r\n style=\"padding:5px 8px;background:#161b22;border:1px solid #30363d;border-radius:5px;\r\n color:#c9d1d9;font-size:11px;outline:none;cursor:pointer;flex-shrink:0\">\r\n <option value=\"be.visible\">be.visible</option>\r\n <option value=\"not.exist\">not.exist</option>\r\n <option value=\"be.disabled\">be.disabled</option>\r\n <option value=\"be.checked\">be.checked</option>\r\n <option value=\"contain.text\">contain.text</option>\r\n <option value=\"have.value\">have.value</option>\r\n <option value=\"have.length\">have.length</option>\r\n <option value=\"have.class\">have.class</option>\r\n <option value=\"have.attr\">have.attr</option>\r\n </select>\r\n <input id=\"assert-value\" type=\"text\" placeholder=\"${this.translation.translate('RECORDER.ASSERT_VALUE_PH')}\"\r\n style=\"flex:2;min-width:110px;padding:5px 8px;background:#161b22;border:1px solid #30363d;\r\n border-radius:5px;color:#c9d1d9;font-size:11px;outline:none\"/>\r\n <button id=\"btn-add-assertion\"\r\n style=\"padding:5px 12px;border:none;border-radius:5px;cursor:pointer;\r\n font-size:11px;font-weight:500;background:#2f81f7;color:#fff;\r\n white-space:nowrap;flex-shrink:0\">\r\n ${this.translation.translate('RECORDER.ASSERT_ADD_BTN')}\r\n </button>\r\n </div>\r\n </div>`;\r\n container.insertAdjacentHTML('beforeend', assertionHtml);\r\n\r\n const NO_VALUE_ASSERTIONS = new Set(['be.visible', 'not.exist', 'be.disabled', 'be.checked']);\r\n document.getElementById('btn-add-assertion')?.addEventListener('click', () => {\r\n const sel = (document.getElementById('assert-selector') as HTMLInputElement).value.trim();\r\n const type = (document.getElementById('assert-type') as HTMLSelectElement).value;\r\n const val = (document.getElementById('assert-value') as HTMLInputElement).value.trim();\r\n if (!sel) return;\r\n const cmd = NO_VALUE_ASSERTIONS.has(type) || !val\r\n ? `cy.get('${sel}').should('${type}')`\r\n : `cy.get('${sel}').should('${type}', '${val}')`;\r\n this.recording.appendCommand(cmd);\r\n (document.getElementById('assert-selector') as HTMLInputElement).value = '';\r\n (document.getElementById('assert-value') as HTMLInputElement).value = '';\r\n });\r\n },\r\n willClose: () => {\r\n this.isCommandsDialogOpen = false;\r\n this._previsualizerRef = null;\r\n },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showSavedTestsDialog(): void {\r\n this.toggleModal('isSavedTestsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_SAVED_TESTS'),\r\n html: '<div id=\"saved-tests-modal-content\" style=\"min-height:250px;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n width: 680,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('saved-tests-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('test-editor') as unknown as TestEditorEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n },\r\n willClose: () => { this.isSavedTestsDialogOpen = false; },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showSaveTestDialog(): void {\r\n this.toggleModal('isSaveTestDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.DIALOG_SAVE'),\r\n html: '<div id=\"save-test-modal-content\" style=\"padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('save-test-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('save-test') as unknown as SaveTestEl;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('savetest', (e: CustomEvent) => {\r\n const { description, notes, tags } = e.detail ?? {};\r\n this.onSaveTest(description ?? null, tags ?? [], notes ?? '');\r\n Swal.close();\r\n });\r\n child.addEventListener('saveandexport', (e: CustomEvent) => {\r\n const { description, notes, tags } = e.detail ?? {};\r\n this.onSaveAndExportTest(description ?? null, tags ?? [], notes ?? '');\r\n Swal.close();\r\n });\r\n },\r\n willClose: () => { this.isSaveTestDialogOpen = false; },\r\n });\r\n });\r\n }\r\n\r\n showSettingsDialog(): void {\r\n this.toggleModal('isSettingsDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.SETTINGS'),\r\n html: '<div id=\"settings-modal-content\" style=\"padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n width: 520,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('settings-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('e2e-configuration') as unknown as ConfigEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('smartselectorchange', (e: CustomEvent) => {\r\n this.smartSelectorEnabled = e.detail;\r\n });\r\n child.addEventListener('starthiddenchange', (e: CustomEvent) => {\r\n this.isVisible = !e.detail;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n });\r\n child.addEventListener('resetwidgetposition', () => this.resetWidgetPosition());\r\n },\r\n willClose: () => { this.isSettingsDialogOpen = false; },\r\n });\r\n this.resizePopup();\r\n });\r\n }\r\n\r\n showAdvancedEditorDialog(testId?: number): void {\r\n this.toggleModal('isAdvancedEditorDialogOpen', () => {\r\n Swal.fire({\r\n title: this.translation.translate('MAIN_FRAME.SHOW_ADVANCED_EDITOR'),\r\n html: '<div id=\"advanced-editor-modal-content\" style=\"flex:1;min-height:0;display:flex;flex-direction:column;padding:0\"></div>',\r\n showCloseButton: true,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n width: 780,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const popup = Swal.getPopup();\r\n if (popup) {\r\n popup.style.height = '600px';\r\n const htmlContainer = popup.querySelector('.swal2-html-container') as HTMLElement | null;\r\n if (htmlContainer) {\r\n htmlContainer.style.flex = '1';\r\n htmlContainer.style.minHeight = '0';\r\n htmlContainer.style.overflow = 'hidden';\r\n htmlContainer.style.padding = '0';\r\n htmlContainer.style.margin = '0';\r\n htmlContainer.style.display = 'flex';\r\n htmlContainer.style.flexDirection = 'column';\r\n }\r\n }\r\n const container = document.getElementById('advanced-editor-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('advanced-test-editor') as unknown as AdvancedEditorEl;\r\n child.persistence = this.persistence;\r\n child.translation = this.translation;\r\n if (testId !== undefined) child.testId = testId;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('selectorstrategychange', (e: CustomEvent) => {\r\n this.recording.selectorStrategy = e.detail;\r\n });\r\n child.addEventListener('closemodal', () => Swal.close());\r\n child.addEventListener('openfileeditor', (e: CustomEvent) => {\r\n Swal.close();\r\n setTimeout(() => this.showFileEditorDialog(\r\n e.detail.handle, e.detail.content, e.detail.fileName, e.detail.testId,\r\n e.detail.itBlock, e.detail.interceptorsBlock, e.detail.notes,\r\n ), 150);\r\n });\r\n },\r\n willClose: () => { this.isAdvancedEditorDialogOpen = false; },\r\n });\r\n setTimeout(() => {\r\n const popup = Swal.getPopup();\r\n if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 0 });\r\n }, 0);\r\n });\r\n }\r\n\r\n private showFileEditorDialog(\r\n handle: FileSystemFileHandle,\r\n content: string,\r\n fileName: string,\r\n testId?: number,\r\n itBlock = '',\r\n interceptorsBlock = '',\r\n notes = '',\r\n ): void {\r\n Swal.fire({\r\n title: this.translation.translate('RECORDER.FILE_EDITOR_TITLE'),\r\n html: '<div id=\"file-editor-modal-content\" style=\"padding:0;height:540px\"></div>',\r\n showCloseButton: false,\r\n showConfirmButton: false,\r\n allowOutsideClick: false,\r\n width: 1100,\r\n color: '#e6edf3',\r\n didOpen: () => {\r\n makeSwalDraggable();\r\n setSwal2DataCyAttribute();\r\n const container = document.getElementById('file-editor-modal-content');\r\n if (!container) return;\r\n const child = document.createElement('file-preview') as unknown as FilePreviewEl;\r\n child.translation = this.translation;\r\n child.fileContent = content;\r\n child.fileName = fileName;\r\n child.closeLabel = this.translation.translate('FILE_PREVIEW.BACK_TO_EDITOR');\r\n child.itBlock = itBlock;\r\n child.interceptorsBlock = interceptorsBlock;\r\n child.notes = notes;\r\n container.appendChild(child as unknown as Node);\r\n child.addEventListener('close', () => {\r\n Swal.close();\r\n setTimeout(() => this.showAdvancedEditorDialog(testId), 150);\r\n });\r\n child.addEventListener('save', async (e: CustomEvent) => {\r\n try {\r\n const writable = await handle.createWritable();\r\n await writable.write(e.detail);\r\n await writable.close();\r\n showToast(this.translation.translate('RECORDER.FILE_SAVED_TOAST'));\r\n } catch {\r\n showToast(this.translation.translate('RECORDER.FILE_SAVE_ERROR_TOAST'), false);\r\n }\r\n Swal.close();\r\n setTimeout(() => this.showAdvancedEditorDialog(testId), 150);\r\n });\r\n },\r\n });\r\n this.resizePopup();\r\n }\r\n\r\n // ββ save handlers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private async onSaveTest(description: string | null, tags: string[] = [], notes = ''): Promise<void> {\r\n if (description) {\r\n await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);\r\n this.recording.clearCommands();\r\n this.clearRecordingHistory();\r\n this.cypressCommands = [];\r\n this.interceptors = [];\r\n }\r\n }\r\n\r\n private async onSaveAndExportTest(description: string | null, tags: string[] = [], notes = ''): Promise<void> {\r\n if (description) {\r\n const id = await this.persistence.insertTest(description, this.cypressCommands, this.interceptors, tags, notes);\r\n this.recording.clearCommands();\r\n this.clearRecordingHistory();\r\n this.cypressCommands = [];\r\n this.interceptors = [];\r\n setTimeout(() => this.showAdvancedEditorDialog(id), 300);\r\n }\r\n }\r\n\r\n // ββ helpers βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\r\n\r\n private toggleModal(flag: keyof this, openFn: () => void): void {\r\n if (this[flag]) {\r\n Swal.close();\r\n (this as Record<string, unknown>)[flag as string] = false;\r\n return;\r\n }\r\n (this as Record<string, unknown>)[flag as string] = true;\r\n openFn();\r\n }\r\n\r\n private resizePopup(): void {\r\n setTimeout(() => {\r\n const popup = Swal.getPopup();\r\n if (popup) makeModalResizable(popup, { minWidth: 400, minHeight: 200 });\r\n }, 0);\r\n }\r\n\r\n private render(): void {\r\n const rec = this.isRecording;\r\n const paused = this.isPaused;\r\n this.style.display = this.isVisible ? '' : 'none';\r\n this.shadow.innerHTML = `<style>${getRecorderStyles(rec, paused)}</style>${renderRecorderWidget(rec, paused, this.translation.translate.bind(this.translation))}`;\r\n const toggleBtn = this.shadow.querySelector('[data-action=\"toggle\"]');\r\n toggleBtn?.addEventListener('click', () => {\r\n // A drag ends with a click event we must swallow so it doesn't toggle recording.\r\n if (this.suppressNextToggleClick) { this.suppressNextToggleClick = false; return; }\r\n this.toggle();\r\n });\r\n toggleBtn?.addEventListener('pointerdown', (e) => this.beginWidgetDrag(e as MouseEvent));\r\n this.shadow.querySelector('[data-action=\"pause\"]')\r\n ?.addEventListener('click', () => this.togglePause());\r\n this.shadow.querySelector('[data-action=\"tests\"]')\r\n ?.addEventListener('click', () => this.showSavedTestsDialog());\r\n this.shadow.querySelector('[data-action=\"commands\"]')\r\n ?.addEventListener('click', () => this.showCommandsDialog());\r\n this.shadow.querySelector('[data-action=\"config\"]')\r\n ?.addEventListener('click', () => this.showSettingsDialog());\r\n this.shadow.querySelector('[data-action=\"browse\"]')\r\n ?.addEventListener('click', () => this.showAdvancedEditorDialog());\r\n // Re-apply the dragged position/orientation after every re-render.\r\n this.applyWidgetPosition();\r\n }\r\n}\r\n\r\nif (!customElements.get('lib-e2e-recorder')) {\r\n customElements.define('lib-e2e-recorder', LibE2eRecorderElement);\r\n}\r\n","import type { ExpandDirection } from '../../utils/widget-position.utils';\r\n\r\nconst DIRECTIONS: ExpandDirection[] = ['up-left', 'up-right', 'down-left', 'down-right'];\r\n\r\n/**\r\n * Per-direction anchors + label placement. The toggle sits at the box corner\r\n * nearest the screen edge so the radial arc always expands toward the viewport\r\n * interior (spec 007). --sx/--sy drive the arc transforms; the actual widget\r\n * position (left/top) is set imperatively from JS.\r\n */\r\nfunction directionBlocks(): string {\r\n return DIRECTIONS.map((dir) => {\r\n const sx = dir.endsWith('left') ? -1 : 1;\r\n const sy = dir.startsWith('up') ? -1 : 1;\r\n const tv = dir.startsWith('up') ? 'bottom' : 'top'; // toggle vertical side\r\n const th = dir.endsWith('left') ? 'right' : 'left'; // toggle horizontal side\r\n const ov = tv === 'bottom' ? 'top' : 'bottom'; // interior vertical side\r\n const oh = th === 'right' ? 'left' : 'right'; // interior (arc) horizontal side\r\n const sel = `.widget[data-expand=\"${dir}\"]`;\r\n\r\n // Diagonal labels (n2/n3) sit on the arc's horizontal side; vertical-extreme\r\n // (n1) and horizontal-extreme (n4) labels sit on the interior vertical side.\r\n const labelGeneral = `${sel} .btn-action::after { ${oh}: calc(100% + 9px); ${th}: auto; top: 50%; bottom: auto; transform: translateY(-50%); }`;\r\n const labelEnds = `${sel} .btn-action[data-n=\"1\"]::after, ${sel} .btn-action[data-n=\"4\"]::after { ${ov}: calc(100% + 9px); ${tv}: auto; left: 50%; right: auto; transform: translateX(-50%); }`;\r\n\r\n return `\r\n ${sel} { --sx: ${sx}; --sy: ${sy}; }\r\n ${sel} .btn-toggle { ${tv}: 24px; ${th}: 24px; ${ov}: auto; ${oh}: auto; }\r\n ${sel} .btn-pause { ${tv}: 78px; ${th}: 24px; ${ov}: auto; ${oh}: auto; }\r\n ${sel} .btn-action { ${tv}: 28px; ${th}: 28px; ${ov}: auto; ${oh}: auto; }\r\n ${labelGeneral}\r\n ${labelEnds}\r\n `;\r\n }).join('\\n');\r\n}\r\n\r\nexport function getRecorderStyles(rec: boolean, paused: boolean): string {\r\n return `\r\n :host { all: initial; }\r\n *, *::before, *::after { box-sizing: border-box; }\r\n\r\n /*\r\n * Invisible 190Γ190 hit area. Position (left/top) is set from JS so the\r\n * widget can be dragged; --sx/--sy + data-expand orient the radial menu so\r\n * it always expands toward the viewport interior. Defaults to bottom-right.\r\n */\r\n .widget {\r\n position: fixed;\r\n bottom: 0;\r\n right: 0;\r\n width: 190px;\r\n height: 190px;\r\n z-index: 2147483647;\r\n --sx: -1;\r\n --sy: -1;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n }\r\n\r\n /* ββ Toggle ββββββββββββββββββββββββββββββββββββββββ */\r\n .btn-toggle {\r\n position: absolute;\r\n bottom: 24px;\r\n right: 24px;\r\n width: 44px;\r\n height: 44px;\r\n border-radius: 50%;\r\n border: none;\r\n cursor: grab;\r\n touch-action: none;\r\n font-size: 19px;\r\n background: ${rec\r\n ? 'linear-gradient(135deg,#f85149 0%,#da3633 100%)'\r\n : 'linear-gradient(135deg,#2f81f7 0%,#1f6feb 100%)'};\r\n color: #fff;\r\n box-shadow: ${rec\r\n ? '0 4px 20px rgba(248,81,73,.55),0 0 0 4px rgba(248,81,73,.13)'\r\n : '0 4px 20px rgba(47,129,247,.45),0 0 0 4px rgba(47,129,247,.11)'};\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: transform .18s, box-shadow .2s;\r\n z-index: 2;\r\n ${rec ? 'animation: toggle-pulse 2s ease-in-out infinite;' : ''}\r\n }\r\n .btn-toggle:hover { transform: scale(1.1); }\r\n .btn-toggle:active { transform: scale(0.93); cursor: grabbing; }\r\n\r\n @keyframes toggle-pulse {\r\n 0%,100% { box-shadow: 0 4px 20px rgba(248,81,73,.55),0 0 0 4px rgba(248,81,73,.13); }\r\n 50% { box-shadow: 0 6px 28px rgba(248,81,73,.75),0 0 0 8px rgba(248,81,73,.06); }\r\n }\r\n\r\n /* ββ Pause button ββββββββββββββββββββββββββββββββββ */\r\n .btn-pause {\r\n position: absolute;\r\n bottom: 78px;\r\n right: 24px;\r\n width: 34px;\r\n height: 34px;\r\n border-radius: 50%;\r\n border: none;\r\n cursor: pointer;\r\n font-size: 15px;\r\n display: ${rec ? 'flex' : 'none'};\r\n align-items: center;\r\n justify-content: center;\r\n background: ${paused\r\n ? 'linear-gradient(135deg,#2f81f7 0%,#1f6feb 100%)'\r\n : 'rgba(13,17,23,0.85)'};\r\n color: ${paused ? '#fff' : '#e3b341'};\r\n box-shadow: 0 2px 12px rgba(0,0,0,.4), 0 0 0 1px rgba(48,54,61,.8);\r\n transition: transform .15s, background .2s, color .2s;\r\n z-index: 2;\r\n }\r\n .btn-pause:hover { transform: scale(1.12); }\r\n .btn-pause:active { transform: scale(0.93); }\r\n\r\n /* ββ Action buttons ββββββββββββββββββββββββββββββββ */\r\n .btn-action {\r\n position: absolute;\r\n bottom: 28px;\r\n right: 28px;\r\n width: 36px;\r\n height: 36px;\r\n border-radius: 50%;\r\n border: none;\r\n cursor: pointer;\r\n font-size: 16px;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n background: rgba(13,17,23,.92);\r\n backdrop-filter: blur(14px);\r\n -webkit-backdrop-filter: blur(14px);\r\n color: #8b949e;\r\n box-shadow: 0 4px 18px rgba(0,0,0,.45), 0 0 0 1px rgba(48,54,61,.75);\r\n opacity: 0;\r\n transform: scale(0.35);\r\n pointer-events: none;\r\n transition: opacity .15s, transform .18s ease-in,\r\n background .15s, color .12s, box-shadow .15s;\r\n }\r\n\r\n /* Label chip */\r\n .btn-action::after {\r\n content: attr(data-label);\r\n position: absolute;\r\n right: calc(100% + 9px);\r\n top: 50%;\r\n transform: translateY(-50%);\r\n background: rgba(13,17,23,.95);\r\n color: #e6edf3;\r\n font-size: 11px;\r\n font-weight: 500;\r\n padding: 3px 9px;\r\n border-radius: 6px;\r\n white-space: nowrap;\r\n pointer-events: none;\r\n opacity: 0;\r\n transition: opacity .15s .05s;\r\n border: 1px solid rgba(48,54,61,.8);\r\n box-shadow: 0 2px 8px rgba(0,0,0,.35);\r\n }\r\n .btn-action:hover::after { opacity: 1; }\r\n .btn-action:hover { background: #21262d; color: #e6edf3; }\r\n .btn-action:active { background: #30363d !important; }\r\n\r\n /* Expand: spring + stagger */\r\n .widget:hover .btn-action {\r\n opacity: 1;\r\n pointer-events: all;\r\n transition: opacity .2s, transform .32s cubic-bezier(.34,1.56,.64,1),\r\n background .15s, color .12s, box-shadow .15s;\r\n }\r\n\r\n /* Arc positions β signs come from --sx/--sy (data-expand) */\r\n .widget:hover .btn-action[data-n=\"1\"] { /* vertical extreme */\r\n transform: translateY(calc(var(--sy) * 90px)) scale(1);\r\n transition-delay: .03s;\r\n }\r\n .widget:hover .btn-action[data-n=\"2\"] { /* diagonal near-vertical */\r\n transform: translate(calc(var(--sx) * 45px), calc(var(--sy) * 78px)) scale(1);\r\n transition-delay: .07s;\r\n }\r\n .widget:hover .btn-action[data-n=\"3\"] { /* diagonal near-horizontal */\r\n transform: translate(calc(var(--sx) * 78px), calc(var(--sy) * 45px)) scale(1);\r\n transition-delay: .11s;\r\n }\r\n .widget:hover .btn-action[data-n=\"4\"] { /* horizontal extreme */\r\n transform: translateX(calc(var(--sx) * 90px)) scale(1);\r\n transition-delay: .15s;\r\n }\r\n\r\n /* Per-direction anchors + label sides */\r\n ${directionBlocks()}\r\n\r\n /* ββ REC / PAUSED badge ββββββββββββββββββββββββββββ */\r\n .rec-badge {\r\n position: fixed;\r\n top: 14px;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n background: ${paused\r\n ? 'linear-gradient(90deg,#e3b341,#d29922)'\r\n : 'linear-gradient(90deg,#f85149,#da3633)'};\r\n color: #fff;\r\n padding: 3px 16px;\r\n border-radius: 20px;\r\n font-size: 10px;\r\n font-weight: 700;\r\n letter-spacing: 2px;\r\n text-transform: uppercase;\r\n z-index: 2147483647;\r\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\r\n box-shadow: ${paused\r\n ? '0 4px 16px rgba(227,179,65,.4)'\r\n : '0 4px 16px rgba(248,81,73,.4)'};\r\n display: ${rec ? 'block' : 'none'};\r\n ${!paused ? 'animation: rec-pulse 1.8s ease-in-out infinite;' : ''}\r\n }\r\n @keyframes rec-pulse {\r\n 0%,100% { opacity: 1; }\r\n 50% { opacity: 0.6; }\r\n }\r\n `;\r\n}\r\n","export function renderRecorderWidget(rec: boolean, paused: boolean, t: (key: string) => string): string {\n return `\n <div class=\"widget\">\n <button class=\"btn-action\" data-n=\"1\" data-action=\"config\"\n data-label=\"${t('RECORDER.BTN_CONFIG')}\">βοΈ</button>\n <button class=\"btn-action\" data-n=\"2\" data-action=\"browse\"\n data-label=\"${t('RECORDER.BTN_FILES')}\">π</button>\n <button class=\"btn-action\" data-n=\"3\" data-action=\"commands\"\n data-label=\"${t('RECORDER.BTN_COMMANDS')}\">β¨οΈ</button>\n <button class=\"btn-action\" data-n=\"4\" data-action=\"tests\"\n data-label=\"${t('RECORDER.BTN_TESTS')}\">π</button>\n <button class=\"btn-pause\" data-action=\"pause\"\n title=\"${paused ? t('RECORDER.RESUME_TITLE') : t('RECORDER.PAUSE_TITLE')}\">\n ${paused ? 'βΆ' : 'βΈ'}\n </button>\n <button class=\"btn-toggle\" data-action=\"toggle\"\n title=\"${rec ? t('RECORDER.STOP_TITLE') : t('RECORDER.START_TITLE')}\">\n ${rec ? 'βΉ' : 'βΊ'}\n </button>\n </div>\n <div class=\"rec-badge\">${paused ? t('RECORDER.BADGE_PAUSED') : t('RECORDER.BADGE_REC')}</div>`;\n}\n"],"mappings":"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","names":["tag","container","rect","input","folderInput","i","j","Swal"]}
|