craftdriver 0.1.0 → 0.2.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.
Files changed (186) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/README.md +157 -45
  3. package/bin/craftdriver.mjs +26 -0
  4. package/dist/cli/client.d.ts +17 -0
  5. package/dist/cli/client.d.ts.map +1 -0
  6. package/dist/cli/client.js +88 -0
  7. package/dist/cli/client.js.map +1 -0
  8. package/dist/cli/daemon.d.ts +15 -0
  9. package/dist/cli/daemon.d.ts.map +1 -0
  10. package/dist/cli/daemon.js +145 -0
  11. package/dist/cli/daemon.js.map +1 -0
  12. package/dist/cli/defaults.d.ts +10 -0
  13. package/dist/cli/defaults.d.ts.map +1 -0
  14. package/dist/cli/defaults.js +42 -0
  15. package/dist/cli/defaults.js.map +1 -0
  16. package/dist/cli/dispatcher.d.ts +28 -0
  17. package/dist/cli/dispatcher.d.ts.map +1 -0
  18. package/dist/cli/dispatcher.js +319 -0
  19. package/dist/cli/dispatcher.js.map +1 -0
  20. package/dist/cli/index.d.ts +2 -0
  21. package/dist/cli/index.d.ts.map +1 -0
  22. package/dist/cli/index.js +404 -0
  23. package/dist/cli/index.js.map +1 -0
  24. package/dist/cli/init.d.ts +24 -0
  25. package/dist/cli/init.d.ts.map +1 -0
  26. package/dist/cli/init.js +192 -0
  27. package/dist/cli/init.js.map +1 -0
  28. package/dist/cli/mcp/artifacts.d.ts +43 -0
  29. package/dist/cli/mcp/artifacts.d.ts.map +1 -0
  30. package/dist/cli/mcp/artifacts.js +104 -0
  31. package/dist/cli/mcp/artifacts.js.map +1 -0
  32. package/dist/cli/mcp/server.d.ts +34 -0
  33. package/dist/cli/mcp/server.d.ts.map +1 -0
  34. package/dist/cli/mcp/server.js +214 -0
  35. package/dist/cli/mcp/server.js.map +1 -0
  36. package/dist/cli/mcp/tools.d.ts +34 -0
  37. package/dist/cli/mcp/tools.d.ts.map +1 -0
  38. package/dist/cli/mcp/tools.js +236 -0
  39. package/dist/cli/mcp/tools.js.map +1 -0
  40. package/dist/cli/parseArgs.d.ts +37 -0
  41. package/dist/cli/parseArgs.d.ts.map +1 -0
  42. package/dist/cli/parseArgs.js +215 -0
  43. package/dist/cli/parseArgs.js.map +1 -0
  44. package/dist/cli/protocol.d.ts +34 -0
  45. package/dist/cli/protocol.d.ts.map +1 -0
  46. package/dist/cli/protocol.js +2 -0
  47. package/dist/cli/protocol.js.map +1 -0
  48. package/dist/cli/selector.d.ts +29 -0
  49. package/dist/cli/selector.d.ts.map +1 -0
  50. package/dist/cli/selector.js +100 -0
  51. package/dist/cli/selector.js.map +1 -0
  52. package/dist/cli/snapshot.d.ts +48 -0
  53. package/dist/cli/snapshot.d.ts.map +1 -0
  54. package/dist/cli/snapshot.js +179 -0
  55. package/dist/cli/snapshot.js.map +1 -0
  56. package/dist/index.d.ts +14 -2
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +15 -1
  59. package/dist/index.js.map +1 -1
  60. package/dist/lib/a11y.d.ts +81 -0
  61. package/dist/lib/a11y.d.ts.map +1 -0
  62. package/dist/lib/a11y.js +171 -0
  63. package/dist/lib/a11y.js.map +1 -0
  64. package/dist/lib/bidi/index.d.ts +26 -1
  65. package/dist/lib/bidi/index.d.ts.map +1 -1
  66. package/dist/lib/bidi/index.js +49 -0
  67. package/dist/lib/bidi/index.js.map +1 -1
  68. package/dist/lib/bidi/logs.d.ts +2 -2
  69. package/dist/lib/bidi/logs.d.ts.map +1 -1
  70. package/dist/lib/bidi/logs.js +2 -2
  71. package/dist/lib/bidi/logs.js.map +1 -1
  72. package/dist/lib/bidi/network.d.ts +74 -1
  73. package/dist/lib/bidi/network.d.ts.map +1 -1
  74. package/dist/lib/bidi/network.js +222 -4
  75. package/dist/lib/bidi/network.js.map +1 -1
  76. package/dist/lib/bidi/storage.d.ts +5 -3
  77. package/dist/lib/bidi/storage.d.ts.map +1 -1
  78. package/dist/lib/bidi/storage.js +14 -7
  79. package/dist/lib/bidi/storage.js.map +1 -1
  80. package/dist/lib/bidi/types.d.ts +27 -6
  81. package/dist/lib/bidi/types.d.ts.map +1 -1
  82. package/dist/lib/browser.d.ts +637 -16
  83. package/dist/lib/browser.d.ts.map +1 -1
  84. package/dist/lib/browser.js +1428 -102
  85. package/dist/lib/browser.js.map +1 -1
  86. package/dist/lib/browserContext.d.ts +486 -0
  87. package/dist/lib/browserContext.d.ts.map +1 -0
  88. package/dist/lib/browserContext.js +937 -0
  89. package/dist/lib/browserContext.js.map +1 -0
  90. package/dist/lib/builder.d.ts +3 -0
  91. package/dist/lib/builder.d.ts.map +1 -1
  92. package/dist/lib/builder.js +31 -4
  93. package/dist/lib/builder.js.map +1 -1
  94. package/dist/lib/by.d.ts +18 -2
  95. package/dist/lib/by.d.ts.map +1 -1
  96. package/dist/lib/by.js +20 -2
  97. package/dist/lib/by.js.map +1 -1
  98. package/dist/lib/chrome.d.ts +13 -1
  99. package/dist/lib/chrome.d.ts.map +1 -1
  100. package/dist/lib/chrome.js +13 -17
  101. package/dist/lib/chrome.js.map +1 -1
  102. package/dist/lib/clock.d.ts +115 -0
  103. package/dist/lib/clock.d.ts.map +1 -0
  104. package/dist/lib/clock.js +407 -0
  105. package/dist/lib/clock.js.map +1 -0
  106. package/dist/lib/driver.d.ts +43 -0
  107. package/dist/lib/driver.d.ts.map +1 -1
  108. package/dist/lib/driver.js +120 -0
  109. package/dist/lib/driver.js.map +1 -1
  110. package/dist/lib/driverManager.d.ts +25 -0
  111. package/dist/lib/driverManager.d.ts.map +1 -0
  112. package/dist/lib/driverManager.js +399 -0
  113. package/dist/lib/driverManager.js.map +1 -0
  114. package/dist/lib/elementHandle.d.ts +67 -3
  115. package/dist/lib/elementHandle.d.ts.map +1 -1
  116. package/dist/lib/elementHandle.js +209 -67
  117. package/dist/lib/elementHandle.js.map +1 -1
  118. package/dist/lib/errors.d.ts +71 -0
  119. package/dist/lib/errors.d.ts.map +1 -0
  120. package/dist/lib/errors.js +73 -0
  121. package/dist/lib/errors.js.map +1 -0
  122. package/dist/lib/expect.d.ts +6 -1
  123. package/dist/lib/expect.d.ts.map +1 -1
  124. package/dist/lib/expect.js +55 -37
  125. package/dist/lib/expect.js.map +1 -1
  126. package/dist/lib/firefox.d.ts +18 -0
  127. package/dist/lib/firefox.d.ts.map +1 -0
  128. package/dist/lib/firefox.js +33 -0
  129. package/dist/lib/firefox.js.map +1 -0
  130. package/dist/lib/frame.d.ts +57 -0
  131. package/dist/lib/frame.d.ts.map +1 -0
  132. package/dist/lib/frame.js +277 -0
  133. package/dist/lib/frame.js.map +1 -0
  134. package/dist/lib/keyboard.d.ts +1 -1
  135. package/dist/lib/keyboard.d.ts.map +1 -1
  136. package/dist/lib/keyboard.js +1 -1
  137. package/dist/lib/keyboard.js.map +1 -1
  138. package/dist/lib/locator.d.ts +71 -2
  139. package/dist/lib/locator.d.ts.map +1 -1
  140. package/dist/lib/locator.js +289 -31
  141. package/dist/lib/locator.js.map +1 -1
  142. package/dist/lib/mouse.d.ts +1 -1
  143. package/dist/lib/mouse.d.ts.map +1 -1
  144. package/dist/lib/mouse.js +1 -1
  145. package/dist/lib/mouse.js.map +1 -1
  146. package/dist/lib/page.d.ts +107 -0
  147. package/dist/lib/page.d.ts.map +1 -0
  148. package/dist/lib/page.js +388 -0
  149. package/dist/lib/page.js.map +1 -0
  150. package/dist/lib/tracing.d.ts +128 -0
  151. package/dist/lib/tracing.d.ts.map +1 -0
  152. package/dist/lib/tracing.js +272 -0
  153. package/dist/lib/tracing.js.map +1 -0
  154. package/dist/lib/wait.d.ts.map +1 -1
  155. package/dist/lib/wait.js +14 -1
  156. package/dist/lib/wait.js.map +1 -1
  157. package/dist/lib/webelement.d.ts +2 -0
  158. package/dist/lib/webelement.d.ts.map +1 -1
  159. package/dist/lib/webelement.js +18 -0
  160. package/dist/lib/webelement.js.map +1 -1
  161. package/docs/accessibility.md +177 -0
  162. package/docs/api-reference.md +71 -0
  163. package/docs/assertions.md +182 -0
  164. package/docs/bidi-features.md +462 -0
  165. package/docs/browser-api.md +673 -0
  166. package/docs/browser-context.md +522 -0
  167. package/docs/cli.md +233 -0
  168. package/docs/clock.md +245 -0
  169. package/docs/dialogs.md +143 -0
  170. package/docs/driver-configuration.md +64 -0
  171. package/docs/element-api.md +219 -0
  172. package/docs/emulation.md +155 -0
  173. package/docs/error-codes.md +67 -0
  174. package/docs/getting-started.md +168 -0
  175. package/docs/keyboard-mouse.md +250 -0
  176. package/docs/mcp.md +250 -0
  177. package/docs/mobile-emulation.md +194 -0
  178. package/docs/screenshots.md +146 -0
  179. package/docs/selectors.md +382 -0
  180. package/docs/session-management.md +229 -0
  181. package/docs/tracing.md +282 -0
  182. package/package.json +23 -6
  183. package/skills/craftdriver/SKILL.md +84 -0
  184. package/skills/craftdriver/cheatsheet.md +194 -0
  185. package/skills/craftdriver/cli.md +104 -0
  186. package/skills/craftdriver/patterns.md +139 -0
@@ -0,0 +1,407 @@
1
+ /**
2
+ * Virtual clock control — freeze, advance, or override the wall clock the
3
+ * page sees: Date.now, new Date(), performance.now, setTimeout, setInterval,
4
+ * requestAnimationFrame.
5
+ */
6
+ import { CraftdriverError, ErrorCode } from './errors.js';
7
+ // ---------------------------------------------------------------------------
8
+ // Fake-timer shim — injected into the page via addInitScript
9
+ // ---------------------------------------------------------------------------
10
+ //
11
+ // The shim:
12
+ // • Captures real globals once (at controller-creation time).
13
+ // • Exposes window.__craftdriverClock__ with install / uninstall / tick /
14
+ // setFixedTime / setSystemTime / runFor.
15
+ // • The controller-creation block is guarded by an existence check so that
16
+ // re-evaluating the script on the same document doesn't re-capture
17
+ // already-faked globals.
18
+ // • Uses only ES5-compatible syntax so it works in every modern browser
19
+ // without transpilation.
20
+ // ---------------------------------------------------------------------------
21
+ const SHIM_SETUP = `(function() {
22
+ if (window.__craftdriverClock__) return;
23
+
24
+ var originals = {
25
+ Date: window.Date,
26
+ setTimeout: window.setTimeout,
27
+ clearTimeout: window.clearTimeout,
28
+ setInterval: window.setInterval,
29
+ clearInterval: window.clearInterval,
30
+ performanceNow: (window.performance && typeof window.performance.now === 'function')
31
+ ? window.performance.now.bind(window.performance)
32
+ : null,
33
+ requestAnimationFrame: typeof window.requestAnimationFrame === 'function'
34
+ ? window.requestAnimationFrame.bind(window)
35
+ : null,
36
+ cancelAnimationFrame: typeof window.cancelAnimationFrame === 'function'
37
+ ? window.cancelAnimationFrame.bind(window)
38
+ : null,
39
+ };
40
+
41
+ var state = {
42
+ installed: false,
43
+ fixedMode: false,
44
+ fixedTime: 0,
45
+ virtualNow: 0,
46
+ performanceOrigin: 0,
47
+ timers: [],
48
+ nextId: 1,
49
+ };
50
+
51
+ function fakeNow() {
52
+ if (state.fixedMode) return state.fixedTime;
53
+ return state.virtualNow;
54
+ }
55
+
56
+ function patchDate() {
57
+ var OrigDate = originals.Date;
58
+ function FakeDate() {
59
+ var t;
60
+ if (arguments.length === 0) {
61
+ t = new OrigDate(fakeNow());
62
+ } else if (arguments.length === 1) {
63
+ t = new OrigDate(arguments[0]);
64
+ } else if (arguments.length === 2) {
65
+ t = new OrigDate(arguments[0], arguments[1]);
66
+ } else if (arguments.length === 3) {
67
+ t = new OrigDate(arguments[0], arguments[1], arguments[2]);
68
+ } else if (arguments.length === 4) {
69
+ t = new OrigDate(arguments[0], arguments[1], arguments[2], arguments[3]);
70
+ } else if (arguments.length === 5) {
71
+ t = new OrigDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
72
+ } else if (arguments.length === 6) {
73
+ t = new OrigDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]);
74
+ } else {
75
+ t = new OrigDate(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
76
+ }
77
+ if (!(this instanceof FakeDate)) return t.toString();
78
+ return t;
79
+ }
80
+ FakeDate.now = function() { return fakeNow(); };
81
+ FakeDate.parse = OrigDate.parse.bind(OrigDate);
82
+ FakeDate.UTC = OrigDate.UTC.bind(OrigDate);
83
+ Object.setPrototypeOf(FakeDate, OrigDate);
84
+ FakeDate.prototype = OrigDate.prototype;
85
+ window.Date = FakeDate;
86
+ }
87
+
88
+ function runTimers(targetTime) {
89
+ while (true) {
90
+ var earliest = null;
91
+ for (var i = 0; i < state.timers.length; i++) {
92
+ var t = state.timers[i];
93
+ if (!t.cancelled && t.deadline <= targetTime) {
94
+ if (!earliest || t.deadline < earliest.deadline ||
95
+ (t.deadline === earliest.deadline && t.id < earliest.id)) {
96
+ earliest = t;
97
+ }
98
+ }
99
+ }
100
+ if (!earliest) break;
101
+
102
+ state.virtualNow = earliest.deadline;
103
+
104
+ if (earliest.interval !== null) {
105
+ earliest.deadline += earliest.interval;
106
+ } else {
107
+ var idx = state.timers.indexOf(earliest);
108
+ if (idx !== -1) state.timers.splice(idx, 1);
109
+ }
110
+
111
+ try {
112
+ if (typeof earliest.fn === 'function') {
113
+ earliest.fn.apply(null, earliest.args || []);
114
+ } else if (typeof earliest.fn === 'string') {
115
+ // setTimeout(codeString, ...) form
116
+ // eslint-disable-next-line no-new-func
117
+ new Function(earliest.fn)();
118
+ }
119
+ } catch (_e) { /* swallow timer errors */ }
120
+ }
121
+ state.virtualNow = targetTime;
122
+ }
123
+
124
+ var controller = {
125
+ install: function(opts) {
126
+ opts = opts || {};
127
+ var startTime = (opts.time != null) ? opts.time : originals.Date.now();
128
+ state.installed = true;
129
+ state.fixedMode = false;
130
+ state.virtualNow = startTime;
131
+ state.performanceOrigin = startTime;
132
+ state.timers = [];
133
+ state.nextId = 1;
134
+
135
+ patchDate();
136
+
137
+ if (window.performance && typeof window.performance.now === 'function') {
138
+ window.performance.now = function() {
139
+ return state.virtualNow - state.performanceOrigin;
140
+ };
141
+ }
142
+
143
+ window.setTimeout = function(fn, delay) {
144
+ var args = [];
145
+ for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);
146
+ var id = state.nextId++;
147
+ var d = (delay == null || isNaN(+delay) || +delay < 0) ? 0 : +delay;
148
+ state.timers.push({ id: id, deadline: state.virtualNow + d, fn: fn, args: args, interval: null, cancelled: false });
149
+ return id;
150
+ };
151
+
152
+ window.clearTimeout = function(id) {
153
+ for (var i = 0; i < state.timers.length; i++) {
154
+ if (state.timers[i].id === id) { state.timers[i].cancelled = true; return; }
155
+ }
156
+ };
157
+
158
+ window.setInterval = function(fn, delay) {
159
+ var args = [];
160
+ for (var i = 2; i < arguments.length; i++) args.push(arguments[i]);
161
+ var id = state.nextId++;
162
+ var d = (delay == null || isNaN(+delay) || +delay < 0) ? 0 : +delay;
163
+ state.timers.push({ id: id, deadline: state.virtualNow + d, fn: fn, args: args, interval: d, cancelled: false });
164
+ return id;
165
+ };
166
+
167
+ window.clearInterval = function(id) {
168
+ for (var i = 0; i < state.timers.length; i++) {
169
+ if (state.timers[i].id === id) { state.timers[i].cancelled = true; return; }
170
+ }
171
+ };
172
+
173
+ if (originals.requestAnimationFrame) {
174
+ window.requestAnimationFrame = function(fn) { return window.setTimeout(fn, 16); };
175
+ window.cancelAnimationFrame = function(id) { window.clearTimeout(id); };
176
+ }
177
+ },
178
+
179
+ uninstall: function() {
180
+ if (!state.installed && !state.fixedMode) return;
181
+ window.Date = originals.Date;
182
+ if (window.performance && originals.performanceNow) {
183
+ window.performance.now = originals.performanceNow;
184
+ }
185
+ window.setTimeout = originals.setTimeout;
186
+ window.clearTimeout = originals.clearTimeout;
187
+ window.setInterval = originals.setInterval;
188
+ window.clearInterval = originals.clearInterval;
189
+ if (originals.requestAnimationFrame) {
190
+ window.requestAnimationFrame = originals.requestAnimationFrame;
191
+ window.cancelAnimationFrame = originals.cancelAnimationFrame;
192
+ }
193
+ state.installed = false;
194
+ state.fixedMode = false;
195
+ state.timers = [];
196
+ },
197
+
198
+ tick: function(ms) {
199
+ if (!state.installed) throw new Error('[craftdriver clock] tick() requires install() first');
200
+ runTimers(state.virtualNow + ms);
201
+ },
202
+
203
+ setFixedTime: function(time) {
204
+ state.fixedMode = true;
205
+ state.fixedTime = time;
206
+ patchDate();
207
+ if (window.performance && typeof window.performance.now === 'function') {
208
+ window.performance.now = function() { return 0; };
209
+ }
210
+ },
211
+
212
+ setSystemTime: function(time) {
213
+ if (!state.installed) throw new Error('[craftdriver clock] setSystemTime() requires install() first');
214
+ var delta = time - state.virtualNow;
215
+ state.virtualNow = time;
216
+ // Shift all pending timer deadlines by the same amount so they remain
217
+ // at the same relative distance from the new "now".
218
+ for (var i = 0; i < state.timers.length; i++) {
219
+ if (!state.timers[i].cancelled) {
220
+ state.timers[i].deadline += delta;
221
+ }
222
+ }
223
+ },
224
+
225
+ runFor: function(ms) {
226
+ if (!state.installed) throw new Error('[craftdriver clock] runFor() requires install() first');
227
+ var target = state.virtualNow + ms;
228
+ while (state.virtualNow < target) {
229
+ var next = Math.min(state.virtualNow + 16, target);
230
+ runTimers(next);
231
+ }
232
+ },
233
+ };
234
+
235
+ window.__craftdriverClock__ = controller;
236
+ })();`;
237
+ // ---------------------------------------------------------------------------
238
+ // Node-side Clock class
239
+ // ---------------------------------------------------------------------------
240
+ /** Controls the virtual clock inside the browser page. */
241
+ export class Clock {
242
+ adapter;
243
+ _preloadHandle = null;
244
+ constructor(adapter) {
245
+ this.adapter = adapter;
246
+ }
247
+ // ── Time helpers ──────────────────────────────────────────────────────────
248
+ parseTime(time) {
249
+ if (typeof time === 'number')
250
+ return time;
251
+ if (time instanceof Date)
252
+ return time.getTime();
253
+ const ms = new Date(time).getTime();
254
+ if (isNaN(ms)) {
255
+ throw new CraftdriverError(ErrorCode.INVALID_ARGUMENT, `clock: cannot parse time "${String(time)}". ` +
256
+ 'Pass a number (ms since epoch), a Date object, or an ISO date string ' +
257
+ 'like "2026-01-01T00:00:00Z".', { detail: { time: String(time) } });
258
+ }
259
+ return ms;
260
+ }
261
+ /**
262
+ * Parse a duration string "MM:SS" or "HH:MM:SS" (numbers can exceed
263
+ * 59, e.g. "90:00" = 90 minutes). A plain number is returned as-is.
264
+ */
265
+ parseDuration(d) {
266
+ if (typeof d === 'number')
267
+ return d;
268
+ const parts = d.split(':').map(Number);
269
+ if (parts.some(isNaN)) {
270
+ throw new CraftdriverError(ErrorCode.INVALID_ARGUMENT, `clock.fastForward: cannot parse duration "${d}". ` +
271
+ 'Pass a number (ms), "MM:SS", or "HH:MM:SS".', { detail: { duration: d } });
272
+ }
273
+ if (parts.length === 2) {
274
+ const [mm, ss] = parts;
275
+ return (mm * 60 + ss) * 1000;
276
+ }
277
+ if (parts.length === 3) {
278
+ const [hh, mm, ss] = parts;
279
+ return (hh * 3600 + mm * 60 + ss) * 1000;
280
+ }
281
+ throw new CraftdriverError(ErrorCode.INVALID_ARGUMENT, `clock.fastForward: cannot parse duration "${d}". ` +
282
+ 'Pass a number (ms), "MM:SS", or "HH:MM:SS".', { detail: { duration: d } });
283
+ }
284
+ // ── Preload script management ──────────────────────────────────────────────
285
+ async registerPreload(methodCall) {
286
+ if (this._preloadHandle) {
287
+ await this._preloadHandle.remove();
288
+ this._preloadHandle = null;
289
+ }
290
+ const script = `${SHIM_SETUP}\nwindow.__craftdriverClock__.${methodCall};`;
291
+ this._preloadHandle = await this.adapter.addInitScript(script);
292
+ }
293
+ /**
294
+ * Evaluate the shim + method call in the current document, ignoring errors
295
+ * that occur when no page is loaded yet (about:blank / no context).
296
+ */
297
+ async applyNow(methodCall) {
298
+ const script = `${SHIM_SETUP}\nwindow.__craftdriverClock__.${methodCall}`;
299
+ try {
300
+ await this.adapter.evaluate(script);
301
+ }
302
+ catch {
303
+ // No document loaded yet — the preload script will handle it on next navigate.
304
+ }
305
+ }
306
+ // ── Public API ─────────────────────────────────────────────────────────────
307
+ /**
308
+ * Install fake timers in the browser page.
309
+ *
310
+ * Patches `Date`, `performance.now`, `setTimeout`, `setInterval`,
311
+ * `clearTimeout`, `clearInterval`, `requestAnimationFrame`, and
312
+ * `cancelAnimationFrame`. Timers only fire when you call `tick()`,
313
+ * `fastForward()`, or `runFor()`.
314
+ *
315
+ * Also registers a preload script so the fake clock is re-installed
316
+ * automatically on every subsequent navigation.
317
+ *
318
+ * @example
319
+ * await browser.clock.install({ time: '2026-01-01T09:00:00Z' });
320
+ * await browser.navigateTo('/dashboard');
321
+ * await browser.clock.fastForward('15:01');
322
+ */
323
+ async install(options) {
324
+ const timeMs = options?.time !== undefined ? this.parseTime(options.time) : Date.now();
325
+ const methodCall = `install({time: ${timeMs}})`;
326
+ await this.registerPreload(methodCall);
327
+ await this.applyNow(methodCall);
328
+ }
329
+ /**
330
+ * Uninstall fake timers and restore the real `Date`, `setTimeout`, etc.
331
+ * Also removes the preload script so navigations use the real clock again.
332
+ */
333
+ async uninstall() {
334
+ if (this._preloadHandle) {
335
+ await this._preloadHandle.remove();
336
+ this._preloadHandle = null;
337
+ }
338
+ await this.applyNow('uninstall()');
339
+ }
340
+ /**
341
+ * Advance the fake clock by `ms` milliseconds and fire all timers that
342
+ * come due within that window.
343
+ *
344
+ * Requires `install()` to have been called first.
345
+ */
346
+ async tick(ms) {
347
+ await this.adapter.evaluate(`window.__craftdriverClock__.tick(${ms})`);
348
+ }
349
+ /**
350
+ * Advance the fake clock and fire due timers.
351
+ * Accepts a number of milliseconds **or** a duration string:
352
+ * `"MM:SS"` (e.g. `"15:01"` = 15 min 1 s) or `"HH:MM:SS"`.
353
+ *
354
+ * Requires `install()` to have been called first.
355
+ *
356
+ * @example
357
+ * await browser.clock.fastForward('15:01'); // advance 15 minutes 1 second
358
+ * await browser.clock.fastForward(60_000); // advance 60 seconds
359
+ */
360
+ async fastForward(duration) {
361
+ const ms = this.parseDuration(duration);
362
+ await this.tick(ms);
363
+ }
364
+ /**
365
+ * Freeze `Date.now()` / `new Date()` at the given instant.
366
+ *
367
+ * Unlike `install()`, this does **not** fake `setTimeout` or `setInterval`;
368
+ * real timers continue to fire. Use this when you only need to control
369
+ * what "now" is for date-based rendering.
370
+ *
371
+ * Also registers a preload script so the fixed date persists across
372
+ * navigations.
373
+ *
374
+ * @example
375
+ * await browser.clock.setFixedTime('2026-06-15T23:59:00Z');
376
+ * await browser.navigateTo('/billing');
377
+ * await browser.expect('#trial-banner').toContainText('expires today');
378
+ */
379
+ async setFixedTime(time) {
380
+ const ms = this.parseTime(time);
381
+ const methodCall = `setFixedTime(${ms})`;
382
+ await this.registerPreload(methodCall);
383
+ await this.applyNow(methodCall);
384
+ }
385
+ /**
386
+ * Move the fake clock to `time` without advancing the timer queue.
387
+ * Timers that were scheduled continue to fire at their original
388
+ * relative offsets from the new base time when you call `tick()`.
389
+ *
390
+ * Requires `install()` to have been called first.
391
+ */
392
+ async setSystemTime(time) {
393
+ const ms = this.parseTime(time);
394
+ await this.adapter.evaluate(`window.__craftdriverClock__.setSystemTime(${ms})`);
395
+ }
396
+ /**
397
+ * Advance the fake clock by `ms` milliseconds, yielding between each
398
+ * ~16 ms frame so that microtasks and promise callbacks resolve in the
399
+ * correct order.
400
+ *
401
+ * Requires `install()` to have been called first.
402
+ */
403
+ async runFor(ms) {
404
+ await this.adapter.evaluate(`window.__craftdriverClock__.runFor(${ms})`);
405
+ }
406
+ }
407
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/lib/clock.ts"],"names":[],"mappings":"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"}
@@ -10,12 +10,26 @@ export declare class Driver {
10
10
  constructor(endpoint: WebDriverEndpoint, sessionId: string);
11
11
  static create(endpoint: WebDriverEndpoint, caps: Capabilities): Promise<Driver>;
12
12
  navigateTo(url: string): Promise<void>;
13
+ /** W3C `POST /session/{id}/back` — navigate the current top-level browsing context back one step. */
14
+ back(): Promise<void>;
15
+ /** W3C `POST /session/{id}/forward` — navigate forward one step in the joint session history. */
16
+ forward(): Promise<void>;
17
+ /** W3C `POST /session/{id}/refresh` — reload the current top-level browsing context. */
18
+ refresh(): Promise<void>;
13
19
  quit(): Promise<void>;
14
20
  getCurrentUrl(): Promise<string>;
15
21
  getTitle(): Promise<string>;
16
22
  findElement(locator: By): Promise<WebElement>;
17
23
  findElements(locator: By): Promise<WebElement[]>;
18
24
  executeScript<T = unknown>(script: string, args?: unknown[]): Promise<T>;
25
+ /**
26
+ * Execute an asynchronous script. The script receives a callback as its
27
+ * last argument and must invoke it with the result (or with no argument
28
+ * for `undefined`). Resolves with the value passed to the callback.
29
+ */
30
+ executeAsyncScript<T = unknown>(script: string, args?: unknown[]): Promise<T>;
31
+ /** Configure the script (and async-script) timeout in milliseconds. */
32
+ setScriptTimeout(ms: number): Promise<void>;
19
33
  wait<T>(condition: Condition<T>, options?: WaitOptions & {
20
34
  message?: string;
21
35
  }): Promise<T>;
@@ -32,6 +46,35 @@ export declare class Driver {
32
46
  performTouchSwipe(from: [number, number], to: [number, number], durationMs?: number): Promise<void>;
33
47
  performTouchPinch(center: [number, number], scale?: number, distance?: number, durationMs?: number): Promise<void>;
34
48
  screenshotBase64(): Promise<string>;
49
+ /**
50
+ * W3C `POST /session/{id}/window/rect` — resize / reposition the
51
+ * current top-level browsing context's window. Approximates a
52
+ * viewport resize when BiDi's `browsingContext.setViewport` is not
53
+ * available.
54
+ */
55
+ setWindowRect(rect: {
56
+ width: number;
57
+ height: number;
58
+ x?: number;
59
+ y?: number;
60
+ }): Promise<void>;
61
+ getAlertText(): Promise<string>;
62
+ acceptAlert(): Promise<void>;
63
+ dismissAlert(): Promise<void>;
64
+ sendAlertText(text: string): Promise<void>;
35
65
  __sendActions(actions: any[]): Promise<void>;
66
+ /**
67
+ * Switch to an iframe by null (top-level), numeric index, or element reference.
68
+ * Pass `null` to switch back to the top-level browsing context.
69
+ */
70
+ switchToFrame(id: null | number | {
71
+ elementId: string;
72
+ }): Promise<void>;
73
+ /** Return all window handles for the current session. */
74
+ getWindowHandles(): Promise<string[]>;
75
+ /** Switch focus to the window with the given handle. */
76
+ switchToWindow(handle: string): Promise<void>;
77
+ /** Return the handle for the currently focused window. */
78
+ getCurrentWindowHandle(): Promise<string>;
36
79
  }
37
80
  //# sourceMappingURL=driver.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/lib/driver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAmB,iBAAiB,EAAmB,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAuC,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAiB,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE5E,qBAAa,MAAM;IAKf,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,SAAS;IALnB,sCAAsC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;gBAGd,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,EAAE,MAAM;WAGd,MAAM,CAAC,QAAQ,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IA4B/E,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAUhC,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAU3B,WAAW,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAe7C,YAAY,CAAC,OAAO,EAAE,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAkBhD,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,OAAO,EAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAUlF,IAAI,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IAC1F,IAAI,CAAC,CAAC,EACJ,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,EACvB,SAAS,CAAC,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,CAAC,CAAC;IAgBP,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7D,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxC,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrC,aAAa,CACjB,aAAa,CAAC,EAAE,UAAU,EAC1B,CAAC,CAAC,EAAE,MAAM,EACV,CAAC,CAAC,EAAE,MAAM,EACV,QAAQ,GAAE,MAAU,GACnB,OAAO,CAAC,IAAI,CAAC;IA6BV,SAAS,CAAC,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB5C,OAAO,CAAC,MAAM,GAAE,MAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB1C,YAAY,CAChB,aAAa,CAAC,EAAE,UAAU,EAC1B,CAAC,CAAC,EAAE,MAAM,EACV,CAAC,CAAC,EAAE,MAAM,EACV,MAAM,GAAE,MAAU,EAClB,KAAK,GAAE,MAAU,EACjB,YAAY,GAAE,MAAW,GACxB,OAAO,CAAC,IAAI,CAAC;IA2BV,WAAW,CACf,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,CAAC,GAAE,MAAU,EACb,CAAC,GAAE,MAAU,EACb,QAAQ,GAAE,MAAU,GACnB,OAAO,CAAC,IAAI,CAAC;IAiBV,iBAAiB,CACrB,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACtB,EAAE,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACpB,UAAU,SAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAyBV,iBAAiB,CACrB,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EACxB,KAAK,SAAM,EACX,QAAQ,SAAM,EACd,UAAU,SAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAyCV,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAUnC,aAAa,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAQnD"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/lib/driver.ts"],"names":[],"mappings":"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"}
@@ -37,6 +37,21 @@ export class Driver {
37
37
  const client = new HttpClient(this.endpoint);
38
38
  await client.send({ method: 'POST', path: `/session/${this.sessionId}/url`, body: { url } });
39
39
  }
40
+ /** W3C `POST /session/{id}/back` — navigate the current top-level browsing context back one step. */
41
+ async back() {
42
+ const client = new HttpClient(this.endpoint);
43
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/back`, body: {} });
44
+ }
45
+ /** W3C `POST /session/{id}/forward` — navigate forward one step in the joint session history. */
46
+ async forward() {
47
+ const client = new HttpClient(this.endpoint);
48
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/forward`, body: {} });
49
+ }
50
+ /** W3C `POST /session/{id}/refresh` — reload the current top-level browsing context. */
51
+ async refresh() {
52
+ const client = new HttpClient(this.endpoint);
53
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/refresh`, body: {} });
54
+ }
40
55
  async quit() {
41
56
  const client = new HttpClient(this.endpoint);
42
57
  await client.send({ method: 'DELETE', path: `/session/${this.sessionId}` });
@@ -100,6 +115,29 @@ export class Driver {
100
115
  });
101
116
  return (res?.value ?? res);
102
117
  }
118
+ /**
119
+ * Execute an asynchronous script. The script receives a callback as its
120
+ * last argument and must invoke it with the result (or with no argument
121
+ * for `undefined`). Resolves with the value passed to the callback.
122
+ */
123
+ async executeAsyncScript(script, args = []) {
124
+ const client = new HttpClient(this.endpoint);
125
+ const res = await client.send({
126
+ method: 'POST',
127
+ path: `/session/${this.sessionId}/execute/async`,
128
+ body: { script, args },
129
+ });
130
+ return (res?.value ?? res);
131
+ }
132
+ /** Configure the script (and async-script) timeout in milliseconds. */
133
+ async setScriptTimeout(ms) {
134
+ const client = new HttpClient(this.endpoint);
135
+ await client.send({
136
+ method: 'POST',
137
+ path: `/session/${this.sessionId}/timeouts`,
138
+ body: { script: ms },
139
+ });
140
+ }
103
141
  wait(condition, a, b, c) {
104
142
  // Overload: prefer options object, but accept legacy positional args
105
143
  if (typeof a === 'object') {
@@ -342,6 +380,50 @@ export class Driver {
342
380
  });
343
381
  return String(res?.value ?? res ?? '');
344
382
  }
383
+ /**
384
+ * W3C `POST /session/{id}/window/rect` — resize / reposition the
385
+ * current top-level browsing context's window. Approximates a
386
+ * viewport resize when BiDi's `browsingContext.setViewport` is not
387
+ * available.
388
+ */
389
+ async setWindowRect(rect) {
390
+ const client = new HttpClient(this.endpoint);
391
+ const body = { width: rect.width, height: rect.height };
392
+ if (rect.x !== undefined)
393
+ body.x = rect.x;
394
+ if (rect.y !== undefined)
395
+ body.y = rect.y;
396
+ await client.send({
397
+ method: 'POST',
398
+ path: `/session/${this.sessionId}/window/rect`,
399
+ body,
400
+ });
401
+ }
402
+ // --- Alert / dialog endpoints (W3C Classic WebDriver) ---
403
+ async getAlertText() {
404
+ const client = new HttpClient(this.endpoint);
405
+ const res = await client.send({
406
+ method: 'GET',
407
+ path: `/session/${this.sessionId}/alert/text`,
408
+ });
409
+ return String(res?.value ?? res ?? '');
410
+ }
411
+ async acceptAlert() {
412
+ const client = new HttpClient(this.endpoint);
413
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/alert/accept`, body: {} });
414
+ }
415
+ async dismissAlert() {
416
+ const client = new HttpClient(this.endpoint);
417
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/alert/dismiss`, body: {} });
418
+ }
419
+ async sendAlertText(text) {
420
+ const client = new HttpClient(this.endpoint);
421
+ await client.send({
422
+ method: 'POST',
423
+ path: `/session/${this.sessionId}/alert/text`,
424
+ body: { text },
425
+ });
426
+ }
345
427
  // Internal helper for ActionsBuilder to send combined payloads
346
428
  async __sendActions(actions) {
347
429
  const client = new HttpClient(this.endpoint);
@@ -351,5 +433,43 @@ export class Driver {
351
433
  body: { actions },
352
434
  });
353
435
  }
436
+ // --- Frame / window switching (W3C Classic WebDriver) ---
437
+ /**
438
+ * Switch to an iframe by null (top-level), numeric index, or element reference.
439
+ * Pass `null` to switch back to the top-level browsing context.
440
+ */
441
+ async switchToFrame(id) {
442
+ const client = new HttpClient(this.endpoint);
443
+ let bodyId;
444
+ if (id === null) {
445
+ bodyId = null;
446
+ }
447
+ else if (typeof id === 'number') {
448
+ bodyId = id;
449
+ }
450
+ else {
451
+ bodyId = { [W3C_ELEMENT_KEY]: id.elementId, [LEGACY_ELEMENT_KEY]: id.elementId };
452
+ }
453
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/frame`, body: { id: bodyId } });
454
+ }
455
+ /** Return all window handles for the current session. */
456
+ async getWindowHandles() {
457
+ const client = new HttpClient(this.endpoint);
458
+ const res = await client.send({ method: 'GET', path: `/session/${this.sessionId}/window/handles` });
459
+ const v = res?.value ?? res;
460
+ return Array.isArray(v) ? v : [];
461
+ }
462
+ /** Switch focus to the window with the given handle. */
463
+ async switchToWindow(handle) {
464
+ const client = new HttpClient(this.endpoint);
465
+ await client.send({ method: 'POST', path: `/session/${this.sessionId}/window`, body: { handle } });
466
+ }
467
+ /** Return the handle for the currently focused window. */
468
+ async getCurrentWindowHandle() {
469
+ const client = new HttpClient(this.endpoint);
470
+ const res = await client.send({ method: 'GET', path: `/session/${this.sessionId}/window` });
471
+ const v = res?.value ?? res;
472
+ return String(v ?? '');
473
+ }
354
474
  }
355
475
  //# sourceMappingURL=driver.js.map