lib-e2e-cypress-for-dummys-ts 0.3.0 → 0.5.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/dist/index.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  type Lang = 'es' | 'en' | 'fr' | 'it' | 'de';
2
2
  declare const SUPPORTED_LANGS: Lang[];
3
3
  declare function isLang(value: string): value is Lang;
4
+ /** BCP-47 locale used for date/number formatting per UI language. */
5
+ declare const LOCALE_BY_LANG: Record<Lang, string>;
6
+ /** Returns the formatting locale for a UI language (falls back to es-ES). */
7
+ declare function localeForLang(lang: string): string;
4
8
 
5
9
  declare const INPUT_TYPES: readonly ["text", "password", "email", "search", "tel", "url", "number", "textarea"];
6
10
  type InputType = (typeof INPUT_TYPES)[number];
@@ -22,51 +26,7 @@ interface DBSchema {
22
26
  stores: DBStore[];
23
27
  }
24
28
  declare const DB_SCHEMA: DBSchema;
25
- declare const DB_STORE_NAMES: ["tests", "commands", "interceptors", "configuration"];
26
-
27
- declare class TranslationService {
28
- private lang;
29
- private readonly translations;
30
- constructor();
31
- setLang(lang: Lang): void;
32
- getLang(): Lang;
33
- translate(key: string): string;
34
- detectLang(): Lang;
35
- }
36
- declare const translationService: TranslationService;
37
-
38
- declare class TransformationService {
39
- toLang(lang: string): Lang;
40
- generateItDescription(description: string, commands: string[]): string;
41
- }
42
- declare const transformationService: TransformationService;
43
-
44
- interface DirectoryNode {
45
- name: string;
46
- kind: 'directory';
47
- children: (DirectoryNode | FileNode)[];
48
- }
49
- interface FileNode {
50
- name: string;
51
- kind: 'file';
52
- }
53
- declare class AdvancedTestTransformationService {
54
- insertBeforeEach(content: string, interceptors: string, alertFn?: (msg: string) => void): string;
55
- insertItBlock(content: string, itBlock: string, alertFn?: (msg: string) => void): string;
56
- buildBlockComment(notes: string): string;
57
- isFile(file: unknown): boolean;
58
- scanDirectory(dirHandle: FileSystemDirectoryHandle): Promise<DirectoryNode>;
59
- }
60
- declare const advancedTestTransformationService: AdvancedTestTransformationService;
61
-
62
- declare class Subject<T> {
63
- private _value;
64
- private listeners;
65
- constructor(initialValue: T);
66
- next(value: T): void;
67
- getValue(): T;
68
- subscribe(fn: (v: T) => void): () => void;
69
- }
29
+ declare const DB_STORE_NAMES: ["tests", "commands", "interceptors", "configuration", "activeSession"];
70
30
 
71
31
  type SelectorStrategy = 'data-cy' | 'data-testid' | 'aria-label' | 'id';
72
32
  declare class RecordingService {
@@ -78,10 +38,22 @@ declare class RecordingService {
78
38
  private readonly inputDebounceTimers;
79
39
  private readonly abort;
80
40
  selectorStrategy: SelectorStrategy;
41
+ /** Stable id of the current live session (null when none has started). */
42
+ sessionId: string | null;
43
+ private startedAt;
81
44
  private readonly origPushState;
82
45
  private readonly origReplaceState;
83
46
  constructor();
84
47
  startRecording(): void;
48
+ /**
49
+ * Rehydrates a previously persisted session WITHOUT running the startRecording
50
+ * bootstrap (no viewport/visit/hide). Used to continue a recording across a
51
+ * micro-frontend crossing or a same-origin reload.
52
+ * See docs/specs/006-cross-app-recording-continuity.md.
53
+ */
54
+ restoreSession(state: ActiveSessionState): void;
55
+ /** Full snapshot of the live session for persistence. */
56
+ getSessionSnapshot(): ActiveSessionState;
85
57
  stopRecording(): void;
86
58
  toggleRecording(): void;
87
59
  pauseRecording(): void;
@@ -103,6 +75,12 @@ declare class RecordingService {
103
75
  onInterceptorsChange(fn: (ints: string[]) => void): () => void;
104
76
  onRecordingChange(fn: (isRecording: boolean) => void): () => void;
105
77
  onPauseChange(fn: (isPaused: boolean) => void): () => void;
78
+ /**
79
+ * Fires a full session snapshot whenever any persisted field changes
80
+ * (commands, interceptors, recording or paused state). Drives the debounced
81
+ * persistence of the live session. Returns a combined unsubscribe.
82
+ */
83
+ onSessionChange(fn: (state: ActiveSessionState) => void): () => void;
106
84
  onSelectorNotFound(fn: (target: HTMLElement, action: 'click') => void): () => void;
107
85
  destroy(): void;
108
86
  private listenToClicks;
@@ -121,6 +99,82 @@ declare class RecordingService {
121
99
  private urlToWildcard;
122
100
  }
123
101
 
102
+ /**
103
+ * A live, in-progress recording session, persisted so it can survive a
104
+ * micro-frontend crossing (single-spa app swap) or an accidental same-origin
105
+ * reload. Only an actively-recording session is ever stored/resumed.
106
+ *
107
+ * The full payload lives in IndexedDB; a lightweight breadcrumb (sessionId +
108
+ * isRecording + updatedAt) is mirrored to localStorage for synchronous detection.
109
+ *
110
+ * See docs/specs/006-cross-app-recording-continuity.md.
111
+ */
112
+ interface ActiveSessionState {
113
+ /** Stable id for the session, generated when recording starts. */
114
+ sessionId: string;
115
+ isRecording: boolean;
116
+ isPaused: boolean;
117
+ commands: string[];
118
+ interceptors: string[];
119
+ selectorStrategy: SelectorStrategy;
120
+ /** Epoch ms when the session started recording. */
121
+ startedAt: number;
122
+ /** Epoch ms of the last mutation — acts as the recency heartbeat. */
123
+ updatedAt: number;
124
+ }
125
+ /** localStorage key for the synchronous "is a session active?" breadcrumb. */
126
+ declare const ACTIVE_SESSION_BREADCRUMB_KEY = "e2e-active-session";
127
+ /** Configuration key (in the `configuration` store) for the resume recency TTL. */
128
+ declare const RESUME_TTL_CONFIG_KEY = "resumeRecencyTtlMinutes";
129
+ /** Default minutes within which an active session resumes silently. */
130
+ declare const DEFAULT_RESUME_TTL_MINUTES = 30;
131
+
132
+ declare class TranslationService {
133
+ private readonly lang$;
134
+ private readonly translations;
135
+ constructor();
136
+ setLang(lang: Lang): void;
137
+ getLang(): Lang;
138
+ /** Subscribe to language changes; returns an unsubscribe function. */
139
+ onLangChange(fn: (lang: Lang) => void): () => void;
140
+ translate(key: string): string;
141
+ detectLang(): Lang;
142
+ }
143
+ declare const translationService: TranslationService;
144
+
145
+ declare class TransformationService {
146
+ toLang(lang: string): Lang;
147
+ generateItDescription(description: string, commands: string[]): string;
148
+ }
149
+ declare const transformationService: TransformationService;
150
+
151
+ interface DirectoryNode {
152
+ name: string;
153
+ kind: 'directory';
154
+ children: (DirectoryNode | FileNode)[];
155
+ }
156
+ interface FileNode {
157
+ name: string;
158
+ kind: 'file';
159
+ }
160
+ declare class AdvancedTestTransformationService {
161
+ insertBeforeEach(content: string, interceptors: string, alertFn?: (msg: string) => void): string;
162
+ insertItBlock(content: string, itBlock: string, alertFn?: (msg: string) => void): string;
163
+ buildBlockComment(notes: string): string;
164
+ isFile(file: unknown): boolean;
165
+ scanDirectory(dirHandle: FileSystemDirectoryHandle): Promise<DirectoryNode>;
166
+ }
167
+ declare const advancedTestTransformationService: AdvancedTestTransformationService;
168
+
169
+ declare class Subject<T> {
170
+ private _value;
171
+ private listeners;
172
+ constructor(initialValue: T);
173
+ next(value: T): void;
174
+ getValue(): T;
175
+ subscribe(fn: (v: T) => void): () => void;
176
+ }
177
+
124
178
  interface TestRecord {
125
179
  id: number;
126
180
  name: string;
@@ -174,6 +228,12 @@ declare class PersistenceService {
174
228
  setConfigKey(key: string, value: unknown): Promise<void>;
175
229
  getConfig(key: string): Promise<Record<string, unknown> | null>;
176
230
  getGeneralConfig(): Promise<ConfigRecord | null>;
231
+ /** Upserts the live recording session (single record, fixed key). */
232
+ saveActiveSession(state: ActiveSessionState): Promise<void>;
233
+ /** Returns the persisted live session, or null when none is stored. */
234
+ getActiveSession(): Promise<ActiveSessionState | null>;
235
+ /** Removes the live session record. Safe to call when none exists. */
236
+ clearActiveSession(): Promise<void>;
177
237
  clearAllData(): Promise<void>;
178
238
  ingestFileData(tests: Record<string, unknown>[], interceptors: Record<string, unknown>[]): Promise<void>;
179
239
  requestDirectoryPermissions(): Promise<void>;
@@ -212,6 +272,63 @@ declare function setSwal2DataCyAttribute(dataCy?: string): void;
212
272
 
213
273
  declare function showToast(message: string, isSuccess?: boolean): void;
214
274
 
275
+ /** How the user chose which tests to export. */
276
+ type ExportMode = 'all' | 'manual' | 'tags';
277
+ interface ExportSelectionOptions {
278
+ /** Test ids to include in `manual` mode. */
279
+ ids?: Iterable<number>;
280
+ /** Tags to match in `tags` mode. */
281
+ tags?: Iterable<string>;
282
+ }
283
+ /**
284
+ * Returns the subset of tests to export for a given selection mode.
285
+ *
286
+ * - `all` → every test (a shallow copy).
287
+ * - `manual` → tests whose id is in `opts.ids`. Empty/absent ids → none.
288
+ * - `tags` → tests carrying at least one of `opts.tags` (OR semantics).
289
+ * Empty/absent tags → none.
290
+ *
291
+ * Pure: never mutates its inputs.
292
+ */
293
+ declare function selectTestsForExport(tests: TestWithDetails[], mode: ExportMode, opts?: ExportSelectionOptions): TestWithDetails[];
294
+
295
+ /**
296
+ * True when a hostname refers to the local machine — used to gate dev-only
297
+ * features (e.g. launching a Cypress run via the local runner) so they are
298
+ * offered only when the app is served locally, not from a deployed environment.
299
+ *
300
+ * Treats as local: localhost, *.localhost, 127.0.0.1, ::1, 0.0.0.0, and the
301
+ * empty hostname (e.g. file:// URLs). Case-insensitive.
302
+ */
303
+ declare function isLocalHost(hostname: string): boolean;
304
+
305
+ declare class SelectorPickerElement extends HTMLElement {
306
+ targetElement: HTMLElement | null;
307
+ recording: RecordingService;
308
+ translation: TranslationService;
309
+ private shadow;
310
+ private ancestors;
311
+ private rows;
312
+ private selectedIndex;
313
+ private keyHandler;
314
+ private unsubRecording;
315
+ private unsubPause;
316
+ constructor();
317
+ connectedCallback(): void;
318
+ disconnectedCallback(): void;
319
+ private t;
320
+ private buildAncestors;
321
+ private findBestIndex;
322
+ private render;
323
+ private attachKeyListener;
324
+ private detachKeyListener;
325
+ private attachRowClickListeners;
326
+ private subscribeToRecordingChanges;
327
+ private confirm;
328
+ private cancel;
329
+ private closeSilently;
330
+ }
331
+
215
332
  declare class TestPrevisualizerElement extends HTMLElement {
216
333
  private shadow;
217
334
  private _commands;
@@ -294,6 +411,12 @@ declare class ConfigurationElement extends HTMLElement {
294
411
  selectorStrategy: SelectorStrategy;
295
412
  smartSelectorEnabled: boolean;
296
413
  startHidden: boolean;
414
+ resumeTtlMinutes: number;
415
+ isExporting: boolean;
416
+ exportMode: ExportMode;
417
+ exportTests: TestWithDetails[];
418
+ exportSelectedIds: Set<number>;
419
+ exportSelectedTags: Set<string>;
297
420
  private filesystemGranted;
298
421
  private cypressFolderName;
299
422
  constructor();
@@ -303,11 +426,22 @@ declare class ConfigurationElement extends HTMLElement {
303
426
  onLanguageChange(lang: string): Promise<void>;
304
427
  onAdvancedHttpConfigChange(checked: boolean): void;
305
428
  onStartHiddenChange(checked: boolean): Promise<void>;
429
+ onResumeTtlChange(minutes: number): Promise<void>;
306
430
  onSmartSelectorChange(enabled: boolean): Promise<void>;
307
431
  onSelectorStrategyChange(strategy: SelectorStrategy): Promise<void>;
308
432
  changeFolder(): Promise<void>;
309
433
  revokeAccess(): Promise<void>;
434
+ private downloadTests;
435
+ /** Downloads every saved test (used by the "Todo" mode and as a direct API). */
310
436
  exportAllData(): Promise<void>;
437
+ /** Opens the export selection dialog, loading the current tests. */
438
+ openExportDialog(): Promise<void>;
439
+ cancelExport(): void;
440
+ setExportMode(mode: ExportMode): void;
441
+ toggleExportTest(id: number): void;
442
+ toggleExportTag(tag: string): void;
443
+ /** Downloads the tests resolved by the current mode + selection. No-op if empty. */
444
+ confirmExport(): void;
311
445
  importAllData(file: File): Promise<void>;
312
446
  private render;
313
447
  }
@@ -330,6 +464,7 @@ declare class AdvancedTestEditorElement extends HTMLElement {
330
464
  previewFileName: string | null;
331
465
  previewFileContent: string | null;
332
466
  isCreatingFile: boolean;
467
+ isCreatingFolder: boolean;
333
468
  collapsedDirs: Set<string>;
334
469
  sidebarWidth: number;
335
470
  private hasPermission;
@@ -342,6 +477,7 @@ declare class AdvancedTestEditorElement extends HTMLElement {
342
477
  private init;
343
478
  getFoldersData(): Promise<void>;
344
479
  createNewFile(rawName: string): Promise<void>;
480
+ createNewFolder(rawName: string): Promise<void>;
345
481
  refreshTree(): Promise<void>;
346
482
  saveCommandsToFile(): Promise<void>;
347
483
  onFileClick(file: unknown): Promise<void>;
@@ -363,11 +499,18 @@ declare class FilePreviewElement extends HTMLElement {
363
499
  translation: TranslationService;
364
500
  itBlock: string;
365
501
  interceptorsBlock: string;
502
+ notes: string;
366
503
  commands: string[];
367
504
  interceptors: string[];
505
+ /** Endpoint of the local Cypress runner. Configurable; defaults to the bundled runner's port. */
506
+ runnerUrl: string;
507
+ /** Whether the app is served locally — gates the launch button. Overridable for tests. */
508
+ isLocal: boolean;
368
509
  private _fileContent;
369
510
  private _originalContent;
370
511
  private _showDiff;
512
+ private _runState;
513
+ private _runOutput;
371
514
  constructor();
372
515
  connectedCallback(): void;
373
516
  private t;
@@ -375,9 +518,21 @@ declare class FilePreviewElement extends HTMLElement {
375
518
  set fileContent(v: string | null);
376
519
  saveFile(): void;
377
520
  onClose(): void;
521
+ /**
522
+ * Runs the current spec headless via the local runner and shows the result.
523
+ * No-op off localhost. Never throws — connection failures surface as an
524
+ * "error" state + toast instead of an unhandled rejection.
525
+ */
378
526
  launchTest(specPath?: string): Promise<void>;
379
527
  copyToClipboard(text: string): void;
380
528
  toggleDiff(): void;
529
+ /**
530
+ * Merges the it() and beforeEach() blocks into the current editor content
531
+ * using the same logic as the automatic "Insert into file" action, so the
532
+ * user does not have to copy/paste manually. Leaves the content untouched
533
+ * (and warns) when the file has no valid describe() block to insert into.
534
+ */
535
+ insertBlocks(): void;
381
536
  private render;
382
537
  }
383
538
 
@@ -390,6 +545,9 @@ declare class LibE2eRecorderElement extends HTMLElement {
390
545
  private interceptorsUnsub?;
391
546
  private pauseUnsub?;
392
547
  private selectorNotFoundUnsub?;
548
+ private langUnsub?;
549
+ private sessionUnsub?;
550
+ private sessionSaveTimer?;
393
551
  private controlFirstTimeData;
394
552
  private _previsualizerRef;
395
553
  private httpMonitor?;
@@ -416,6 +574,27 @@ declare class LibE2eRecorderElement extends HTMLElement {
416
574
  private showSelectorPicker;
417
575
  private initVisibility;
418
576
  private initSelectorStrategy;
577
+ /**
578
+ * On mount, detect a persisted live recording session and either resume it
579
+ * silently (recent) or prompt continue/discard (stale). No-op when there is
580
+ * no actively-recording session.
581
+ */
582
+ private initSessionContinuity;
583
+ private getResumeTtlMinutes;
584
+ /** Rehydrates the recorder from a persisted session (no bootstrap re-emitted). */
585
+ private resumeSessionState;
586
+ private promptResumeOrDiscard;
587
+ /** Debounced persistence of the live session; clears it the moment recording stops. */
588
+ private persistActiveSession;
589
+ private writeSessionBreadcrumb;
590
+ private flushActiveSessionOnDisconnect;
591
+ private clearSessionPersistence;
592
+ /** True when a synchronous breadcrumb marks an active recording session. */
593
+ hasActiveSession(): boolean;
594
+ /** Programmatically resume the persisted session, if any. */
595
+ resumeSession(): void;
596
+ /** Discard the persisted live session (breadcrumb + DB record). */
597
+ discardSession(): void;
419
598
  toggle(): void;
420
599
  togglePause(): void;
421
600
  setLanguage(lang?: string): void;
@@ -444,6 +623,6 @@ declare class LibE2eRecorderElement extends HTMLElement {
444
623
  private render;
445
624
  }
446
625
 
447
- declare const VERSION = "0.1.0";
626
+ declare const VERSION = "0.5.0";
448
627
 
449
- export { AdvancedTestEditorElement, AdvancedTestTransformationService, ConfigurationElement, type DBSchema, type DBStore, type DBStoreIndex, DB_SCHEMA, DB_STORE_NAMES, type DirectoryNode, type FileNode, FilePreviewElement, HttpMonitor, INPUT_TYPES, type InputType, LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES, type Lang, LibE2eRecorderElement, PersistenceService, RecordingService, SCROLLBAR_STYLES, SUPPORTED_LANGS, SaveTestElement, type SelectorStrategy, Subject, type TestDetail, TestEditorElement, TestPrevisualizerElement, type TestWithDetails, TransformationService, TranslationService, VERSION, advancedTestTransformationService, generateAlias, injectStyles, isLang, makeModalResizable, makeSwalDraggable, makeSwalDraggableByContentId, persistenceService, setSwal2DataCyAttribute, showToast, transformationService, translationService };
628
+ export { ACTIVE_SESSION_BREADCRUMB_KEY, type ActiveSessionState, AdvancedTestEditorElement, AdvancedTestTransformationService, ConfigurationElement, type DBSchema, type DBStore, type DBStoreIndex, DB_SCHEMA, DB_STORE_NAMES, DEFAULT_RESUME_TTL_MINUTES, type DirectoryNode, type ExportMode, type ExportSelectionOptions, type FileNode, FilePreviewElement, HttpMonitor, INPUT_TYPES, type InputType, LIB_E2E_CYPRESS_FOR_DUMMYS_SWAL2_STYLES, LOCALE_BY_LANG, type Lang, LibE2eRecorderElement, PersistenceService, RESUME_TTL_CONFIG_KEY, RecordingService, SCROLLBAR_STYLES, SUPPORTED_LANGS, SaveTestElement, SelectorPickerElement, type SelectorStrategy, Subject, type TestDetail, TestEditorElement, TestPrevisualizerElement, type TestWithDetails, TransformationService, TranslationService, VERSION, advancedTestTransformationService, generateAlias, injectStyles, isLang, isLocalHost, localeForLang, makeModalResizable, makeSwalDraggable, makeSwalDraggableByContentId, persistenceService, selectTestsForExport, setSwal2DataCyAttribute, showToast, transformationService, translationService };