very-happy-dom 0.0.7
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 +251 -0
- package/dist/apis/BrowserAPIs.d.ts +93 -0
- package/dist/apis/Clipboard.d.ts +24 -0
- package/dist/apis/FileAPI.d.ts +56 -0
- package/dist/browser/Browser.d.ts +23 -0
- package/dist/browser/BrowserContext.d.ts +21 -0
- package/dist/browser/BrowserFrame.d.ts +25 -0
- package/dist/browser/BrowserPage.d.ts +82 -0
- package/dist/browser/CookieContainer.d.ts +25 -0
- package/dist/events/CustomEvent.d.ts +14 -0
- package/dist/events/VirtualEvent.d.ts +16 -0
- package/dist/http/XMLHttpRequest.d.ts +66 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +3792 -0
- package/dist/network/RequestInterceptor.d.ts +31 -0
- package/dist/network/WebSocket.d.ts +47 -0
- package/dist/nodes/VirtualCommentNode.d.ts +10 -0
- package/dist/nodes/VirtualDocument.d.ts +50 -0
- package/dist/nodes/VirtualElement.d.ts +43 -0
- package/dist/nodes/VirtualNode.d.ts +47 -0
- package/dist/nodes/VirtualTextNode.d.ts +10 -0
- package/dist/observers/IntersectionObserver.d.ts +49 -0
- package/dist/observers/MutationObserver.d.ts +37 -0
- package/dist/observers/ResizeObserver.d.ts +41 -0
- package/dist/parsers/html-parser.d.ts +5 -0
- package/dist/selectors/engine.d.ts +132 -0
- package/dist/storage/Storage.d.ts +14 -0
- package/dist/timers/TimerManager.d.ts +21 -0
- package/dist/webcomponents/CustomElementRegistry.d.ts +22 -0
- package/dist/webcomponents/ShadowRoot.d.ts +23 -0
- package/dist/window/DetachedWindowAPI.d.ts +19 -0
- package/dist/window/GlobalWindow.d.ts +15 -0
- package/dist/window/Window.d.ts +93 -0
- package/dist/xpath/XPathEvaluator.d.ts +16 -0
- package/dist/xpath/XPathResult.d.ts +32 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# VeryHappyDOM
|
|
2
|
+
|
|
3
|
+
A blazing-fast DOM implementation for Bun, built for speed and browser API compatibility.
|
|
4
|
+
|
|
5
|
+
## โก Performance
|
|
6
|
+
|
|
7
|
+
VeryHappyDOM is **16ร to 79,000ร faster** than established DOM implementations:
|
|
8
|
+
|
|
9
|
+
- **HTML Parsing**: 413ns average (34,400ร faster than HappyDOM)
|
|
10
|
+
- **querySelector**: Sub-microsecond to low-microsecond performance
|
|
11
|
+
- **DOM Manipulation**: Microsecond-level performance
|
|
12
|
+
- **Zero Dependencies**: Pure Bun implementation
|
|
13
|
+
|
|
14
|
+
See [benchmarks](../benchmarks/README.md) for detailed performance comparisons.
|
|
15
|
+
|
|
16
|
+
## ๐ฏ Features
|
|
17
|
+
|
|
18
|
+
### Core DOM APIs
|
|
19
|
+
|
|
20
|
+
- โ
HTML parsing and serialization
|
|
21
|
+
- โ
DOM manipulation (createElement, appendChild, innerHTML, etc.)
|
|
22
|
+
- โ
CSS selectors (querySelector, querySelectorAll)
|
|
23
|
+
- โ
Event handling (addEventListener, dispatchEvent, CustomEvent)
|
|
24
|
+
- โ
Document API (getElementById, getElementsByClassName, etc.)
|
|
25
|
+
|
|
26
|
+
### Browser APIs
|
|
27
|
+
|
|
28
|
+
- โ
**Storage** - localStorage, sessionStorage with Proxy support
|
|
29
|
+
- โ
**Timers** - setTimeout, setInterval, requestAnimationFrame
|
|
30
|
+
- โ
**Network** - fetch, XMLHttpRequest, WebSocket, request interception
|
|
31
|
+
- โ
**Observers** - MutationObserver, IntersectionObserver, ResizeObserver
|
|
32
|
+
- โ
**XPath** - Full XPath 1.0 support with document.evaluate()
|
|
33
|
+
- โ
**Events** - CustomEvent, event emitters, page events
|
|
34
|
+
- โ
**Interaction** - click, type, focus, hover, keyboard, mouse
|
|
35
|
+
- โ
**Web Components** - Shadow DOM, Custom Elements
|
|
36
|
+
- โ
**File API** - File, FileReader, FileList
|
|
37
|
+
- โ
**Clipboard** - navigator.clipboard.writeText/readText
|
|
38
|
+
- โ
**Performance** - performance.now/mark/measure
|
|
39
|
+
- โ
**Geolocation** - navigator.geolocation
|
|
40
|
+
|
|
41
|
+
## ๐ฆ Installation
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bun add very-happy-dom
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## ๐ Quick Start
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
import { Window } from 'very-happy-dom'
|
|
51
|
+
|
|
52
|
+
const window = new Window()
|
|
53
|
+
|
|
54
|
+
// Parse HTML
|
|
55
|
+
window.document.body.innerHTML = '<div id="app"><h1>Hello World</h1></div>'
|
|
56
|
+
|
|
57
|
+
// Query DOM
|
|
58
|
+
const app = window.document.getElementById('app')
|
|
59
|
+
const title = window.document.querySelector('h1')
|
|
60
|
+
|
|
61
|
+
console.log(title?.textContent) // "Hello World"
|
|
62
|
+
|
|
63
|
+
// Cleanup
|
|
64
|
+
await window.happyDOM.close()
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## ๐งช Test Coverage
|
|
68
|
+
|
|
69
|
+
VeryHappyDOM has **972+ comprehensive tests** organized by functionality:
|
|
70
|
+
|
|
71
|
+
### Organized Test Suites (586 tests)
|
|
72
|
+
|
|
73
|
+
| Test Suite | Tests | Coverage |
|
|
74
|
+
|-----------|-------|----------|
|
|
75
|
+
| **storage.test.ts** | 50 | localStorage, sessionStorage, isolation, edge cases |
|
|
76
|
+
| **timers.test.ts** | 29 | setTimeout, setInterval, requestAnimationFrame, cleanup |
|
|
77
|
+
| **network.test.ts** | 43 | fetch, XMLHttpRequest, WebSocket, request interception |
|
|
78
|
+
| **observers.test.ts** | 45 | MutationObserver, IntersectionObserver, ResizeObserver |
|
|
79
|
+
| **xpath.test.ts** | 23 | XPath expressions, predicates, axes, result types |
|
|
80
|
+
| **events.test.ts** | 19 | CustomEvent, addEventListener, page events |
|
|
81
|
+
| **interaction.test.ts** | 11 | click, type, focus, hover, keyboard, mouse |
|
|
82
|
+
| **webcomponents.test.ts** | 21 | Shadow DOM, Custom Elements, lifecycle |
|
|
83
|
+
| **browser-apis.test.ts** | 31 | Performance, Clipboard, Geolocation, File API |
|
|
84
|
+
| **integration.test.ts** | 24 | End-to-end scenarios combining features |
|
|
85
|
+
| **security-sanitization.test.ts** | 52 | XSS prevention, script injection, content sanitization |
|
|
86
|
+
| **attribute-property.test.ts** | 127 | Comprehensive attribute and property handling |
|
|
87
|
+
| **selector-engine.test.ts** | 70 | CSS selectors, combinators, pseudo-classes |
|
|
88
|
+
| **advanced-edge-cases.test.ts** | 41 | Complex scenarios and edge cases |
|
|
89
|
+
|
|
90
|
+
### Legacy Test Suites (287+ tests)
|
|
91
|
+
|
|
92
|
+
All legacy tests have been organized in `tests/legacy/` folder:
|
|
93
|
+
|
|
94
|
+
- โ
Basic feature tests (43)
|
|
95
|
+
- โ
Advanced feature tests (35)
|
|
96
|
+
- โ
Final feature tests (32)
|
|
97
|
+
- โ
Additional feature tests
|
|
98
|
+
- โ
Core DOM tests
|
|
99
|
+
- โ
DOM edge cases
|
|
100
|
+
- โ
Pseudo-class selector tests
|
|
101
|
+
|
|
102
|
+
Plus active stress tests:
|
|
103
|
+
|
|
104
|
+
- โ
87 browser API stress tests
|
|
105
|
+
|
|
106
|
+
### Test Organization
|
|
107
|
+
|
|
108
|
+
Tests are logically organized by domain rather than by implementation phase:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
tests/
|
|
112
|
+
โโโ Core Domain Tests (296 tests)
|
|
113
|
+
โ โโโ storage.test.ts # Storage API tests
|
|
114
|
+
โ โโโ timers.test.ts # Timer API tests
|
|
115
|
+
โ โโโ network.test.ts # Network API tests
|
|
116
|
+
โ โโโ observers.test.ts # Observer pattern tests
|
|
117
|
+
โ โโโ xpath.test.ts # XPath evaluation tests
|
|
118
|
+
โ โโโ events.test.ts # Event system tests
|
|
119
|
+
โ โโโ interaction.test.ts # User interaction tests
|
|
120
|
+
โ โโโ webcomponents.test.ts # Web Components tests
|
|
121
|
+
โ โโโ browser-apis.test.ts # Browser API tests
|
|
122
|
+
โ โโโ integration.test.ts # Integration tests
|
|
123
|
+
โ
|
|
124
|
+
โโโ Quality Assurance (27 tests)
|
|
125
|
+
โ โโโ error-handling.test.ts # Error scenarios
|
|
126
|
+
โ โโโ performance.test.ts # Performance regression
|
|
127
|
+
โ
|
|
128
|
+
โโโ Stress Tests (87 tests)
|
|
129
|
+
โ โโโ browser-api.stress.test.ts
|
|
130
|
+
โ
|
|
131
|
+
โโโ Test Utilities
|
|
132
|
+
โ โโโ test-utils.ts # Shared test helpers
|
|
133
|
+
โ
|
|
134
|
+
โโโ Legacy Tests (287+ tests)
|
|
135
|
+
โโโ legacy/ # Old tests preserved
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Running Tests
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# Run specific test suite
|
|
142
|
+
bun test tests/storage.test.ts
|
|
143
|
+
|
|
144
|
+
# Run all tests
|
|
145
|
+
bun test tests/*.test.ts
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## ๐๏ธ Architecture
|
|
149
|
+
|
|
150
|
+
### Window API
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { Window } from 'very-happy-dom'
|
|
154
|
+
|
|
155
|
+
const window = new Window({
|
|
156
|
+
url: 'https://example.com',
|
|
157
|
+
width: 1920,
|
|
158
|
+
height: 1080,
|
|
159
|
+
settings: {
|
|
160
|
+
navigator: {
|
|
161
|
+
userAgent: 'Custom User Agent'
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Browser API
|
|
168
|
+
|
|
169
|
+
```typescript
|
|
170
|
+
import { Browser } from 'very-happy-dom'
|
|
171
|
+
|
|
172
|
+
const browser = new Browser()
|
|
173
|
+
const page = browser.newPage()
|
|
174
|
+
|
|
175
|
+
await page.goto('https://example.com')
|
|
176
|
+
await page.click('#button')
|
|
177
|
+
await page.type('#input', 'Hello')
|
|
178
|
+
|
|
179
|
+
await browser.close()
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## ๐ง Advanced Features
|
|
183
|
+
|
|
184
|
+
### Request Interception
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
await page.setRequestInterception(true, async (request) => {
|
|
188
|
+
// Mock API responses
|
|
189
|
+
request.respond({
|
|
190
|
+
status: 200,
|
|
191
|
+
headers: { 'Content-Type': 'application/json' },
|
|
192
|
+
body: JSON.stringify({ success: true })
|
|
193
|
+
})
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### XPath Support
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
const result = window.document.evaluate(
|
|
201
|
+
'//div[@class="item"]',
|
|
202
|
+
window.document,
|
|
203
|
+
null,
|
|
204
|
+
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
|
|
205
|
+
null
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
for (let i = 0; i < result.snapshotLength; i++) {
|
|
209
|
+
console.log(result.snapshotItem(i))
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Shadow DOM
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const host = window.document.createElement('div')
|
|
217
|
+
const shadow = host.attachShadow({ mode: 'open' })
|
|
218
|
+
|
|
219
|
+
shadow.innerHTML = '<p>Shadow content</p>'
|
|
220
|
+
const p = shadow.querySelector('p')
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Custom Elements
|
|
224
|
+
|
|
225
|
+
```typescript
|
|
226
|
+
class MyComponent extends window.HTMLElement {
|
|
227
|
+
connectedCallback() {
|
|
228
|
+
this.innerHTML = '<h1>Custom Component</h1>'
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
window.customElements.define('my-component', MyComponent)
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## ๐ Benchmarks
|
|
236
|
+
|
|
237
|
+
See the [benchmarks package](../benchmarks) for detailed performance comparisons with HappyDOM and JSDOM.
|
|
238
|
+
|
|
239
|
+
Key results on Apple M3 Pro:
|
|
240
|
+
|
|
241
|
+
- HTML Parsing: **413 ns** (vs HappyDOM 14.20 ms, JSDOM 32.69 ms)
|
|
242
|
+
- querySelector: **741 ns** (vs HappyDOM 14.27 ms, JSDOM 30.74 ms)
|
|
243
|
+
- DOM Manipulation: **35.49 ยตs** (vs HappyDOM 1.06 ms, JSDOM 3.00 ms)
|
|
244
|
+
|
|
245
|
+
## ๐ค Contributing
|
|
246
|
+
|
|
247
|
+
Contributions welcome! Please check the [FEATURE_ROADMAP.md](./FEATURE_ROADMAP.md) for planned features and current status.
|
|
248
|
+
|
|
249
|
+
## ๐ License
|
|
250
|
+
|
|
251
|
+
MIT
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
declare interface GeolocationPosition {
|
|
2
|
+
coords: GeolocationCoordinates
|
|
3
|
+
timestamp: number
|
|
4
|
+
}
|
|
5
|
+
declare interface GeolocationPositionError {
|
|
6
|
+
code: number
|
|
7
|
+
message: string
|
|
8
|
+
}
|
|
9
|
+
declare interface GeolocationOptions {
|
|
10
|
+
enableHighAccuracy?: boolean
|
|
11
|
+
timeout?: number
|
|
12
|
+
maximumAge?: number
|
|
13
|
+
}
|
|
14
|
+
declare interface NotificationOptions {
|
|
15
|
+
body?: string
|
|
16
|
+
icon?: string
|
|
17
|
+
tag?: string
|
|
18
|
+
data?: any
|
|
19
|
+
}
|
|
20
|
+
declare type DataTransferItemList = any[]
|
|
21
|
+
/**
|
|
22
|
+
* Browser APIs implementation
|
|
23
|
+
* Performance, Geolocation, Notifications, Console, etc.
|
|
24
|
+
*/
|
|
25
|
+
/* eslint-disable no-console */
|
|
26
|
+
// Performance API
|
|
27
|
+
export declare class Performance {
|
|
28
|
+
private _marks: any;
|
|
29
|
+
private _measures: any;
|
|
30
|
+
private _startTime: any;
|
|
31
|
+
now(): number;
|
|
32
|
+
mark(name: string): void;
|
|
33
|
+
measure(name: string, startMark?: string, endMark?: string): void;
|
|
34
|
+
clearMarks(name?: string): void;
|
|
35
|
+
clearMeasures(name?: string): void;
|
|
36
|
+
getEntriesByName(name: string): any[];
|
|
37
|
+
}
|
|
38
|
+
// Geolocation API
|
|
39
|
+
export declare class Geolocation {
|
|
40
|
+
getCurrentPosition(success: (position: GeolocationPosition) => void, _error?: (error: GeolocationPositionError) => void, _options?: GeolocationOptions): void;
|
|
41
|
+
watchPosition(success: (position: GeolocationPosition) => void, _error?: (error: GeolocationPositionError) => void, _options?: GeolocationOptions): number;
|
|
42
|
+
clearWatch(id: number): void;
|
|
43
|
+
}
|
|
44
|
+
// Notification API
|
|
45
|
+
export declare class Notification {
|
|
46
|
+
static permission: 'default' | 'granted' | 'denied';
|
|
47
|
+
title: string;
|
|
48
|
+
body?: string;
|
|
49
|
+
icon?: string;
|
|
50
|
+
tag?: string;
|
|
51
|
+
onclick: ((event: Event) => void) | null;
|
|
52
|
+
onclose: ((event: Event) => void) | null;
|
|
53
|
+
onerror: ((event: Event) => void) | null;
|
|
54
|
+
onshow: ((event: Event) => void) | null;
|
|
55
|
+
constructor(title: string, options?: NotificationOptions);
|
|
56
|
+
static requestPermission(): Promise<'default' | 'granted' | 'denied'>;
|
|
57
|
+
close(): void;
|
|
58
|
+
}
|
|
59
|
+
// Enhanced Console API
|
|
60
|
+
export declare class EnhancedConsole {
|
|
61
|
+
private _groups: string[];
|
|
62
|
+
private _timers: any;
|
|
63
|
+
log(args: any[]): void;
|
|
64
|
+
warn(args: any[]): void;
|
|
65
|
+
error(args: any[]): void;
|
|
66
|
+
info(args: any[]): void;
|
|
67
|
+
debug(args: any[]): void;
|
|
68
|
+
table(data: any): void;
|
|
69
|
+
group(label?: string): void;
|
|
70
|
+
groupCollapsed(label?: string): void;
|
|
71
|
+
groupEnd(): void;
|
|
72
|
+
time(label: string): void;
|
|
73
|
+
timeEnd(label: string): void;
|
|
74
|
+
timeLog(label: string, args: any[]): void;
|
|
75
|
+
clear(): void;
|
|
76
|
+
count(label?: any): void;
|
|
77
|
+
assert(condition: boolean, args: any[]): void;
|
|
78
|
+
trace(args: any[]): void;
|
|
79
|
+
private _prefix(): string[];
|
|
80
|
+
}
|
|
81
|
+
// DataTransfer for Drag & Drop
|
|
82
|
+
export declare class DataTransfer {
|
|
83
|
+
private _data: any;
|
|
84
|
+
dropEffect: 'none' | 'copy' | 'link' | 'move';
|
|
85
|
+
effectAllowed: 'none' | 'copy' | 'copyLink' | 'copyMove' | 'link' | 'linkMove' | 'move' | 'all' | 'uninitialized';
|
|
86
|
+
files: File[];
|
|
87
|
+
items: DataTransferItemList;
|
|
88
|
+
types: string[];
|
|
89
|
+
setData(format: string, data: string): void;
|
|
90
|
+
getData(format: string): string;
|
|
91
|
+
clearData(format?: string): void;
|
|
92
|
+
setDragImage(_image: Element, _x: number, _y: number): void;
|
|
93
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Geolocation } from './BrowserAPIs';
|
|
2
|
+
declare type ClipboardItems = ClipboardItem[]
|
|
3
|
+
export declare class Clipboard {
|
|
4
|
+
private _text: any;
|
|
5
|
+
writeText(text: string): Promise<void>;
|
|
6
|
+
readText(): Promise<string>;
|
|
7
|
+
write(data: ClipboardItems): Promise<void>;
|
|
8
|
+
read(): Promise<ClipboardItems>;
|
|
9
|
+
}
|
|
10
|
+
export declare class Navigator {
|
|
11
|
+
clipboard: Clipboard;
|
|
12
|
+
geolocation: Geolocation;
|
|
13
|
+
userAgent: string;
|
|
14
|
+
language: string;
|
|
15
|
+
languages: readonly string[];
|
|
16
|
+
platform: string;
|
|
17
|
+
cookieEnabled: boolean;
|
|
18
|
+
onLine: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare class ClipboardItem {
|
|
21
|
+
constructor(data: Record<string, Blob | string | Promise<Blob | string>>);
|
|
22
|
+
readonly types: string[];
|
|
23
|
+
getType(type: string): Promise<Blob>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
declare interface FilePropertyBag extends BlobPropertyBag {
|
|
2
|
+
lastModified?: number
|
|
3
|
+
}
|
|
4
|
+
declare interface ProgressEvent extends Event {
|
|
5
|
+
lengthComputable: boolean
|
|
6
|
+
loaded: number
|
|
7
|
+
total: number
|
|
8
|
+
}
|
|
9
|
+
declare type EventListener = (event: Event) => void
|
|
10
|
+
/**
|
|
11
|
+
* File API implementation
|
|
12
|
+
* Provides File, FileReader, and FileList for testing file uploads
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* File implementation
|
|
16
|
+
*/
|
|
17
|
+
export declare class VeryHappyFile extends Blob {
|
|
18
|
+
name: string;
|
|
19
|
+
lastModified: number;
|
|
20
|
+
constructor(bits: BlobPart[], name: string, options?: FilePropertyBag);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* FileReader implementation
|
|
24
|
+
*/
|
|
25
|
+
export declare class VeryHappyFileReader {
|
|
26
|
+
static readonly EMPTY: any;
|
|
27
|
+
static readonly LOADING: any;
|
|
28
|
+
static readonly DONE: any;
|
|
29
|
+
readyState: number;
|
|
30
|
+
result: string | ArrayBuffer | null;
|
|
31
|
+
error: Error | null;
|
|
32
|
+
onload: ((event: ProgressEvent) => void) | null;
|
|
33
|
+
onerror: ((event: ProgressEvent) => void) | null;
|
|
34
|
+
onloadstart: ((event: ProgressEvent) => void) | null;
|
|
35
|
+
onloadend: ((event: ProgressEvent) => void) | null;
|
|
36
|
+
onprogress: ((event: ProgressEvent) => void) | null;
|
|
37
|
+
onabort: ((event: ProgressEvent) => void) | null;
|
|
38
|
+
private _eventListeners: any;
|
|
39
|
+
readAsText(blob: Blob, _encoding?: any): void;
|
|
40
|
+
readAsDataURL(blob: Blob): void;
|
|
41
|
+
readAsArrayBuffer(blob: Blob): void;
|
|
42
|
+
readAsBinaryString(blob: Blob): void;
|
|
43
|
+
abort(): void;
|
|
44
|
+
addEventListener(type: string, listener: EventListener): void;
|
|
45
|
+
removeEventListener(type: string, listener: EventListener): void;
|
|
46
|
+
private _trigger(type: string): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* FileList implementation
|
|
50
|
+
*/
|
|
51
|
+
export declare class VeryHappyFileList {
|
|
52
|
+
private _files: File[];
|
|
53
|
+
constructor(files?: File[]);
|
|
54
|
+
item(index: number): File | null;
|
|
55
|
+
[Symbol.iterator](): Iterator<File>;
|
|
56
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { BrowserContext } from './BrowserContext';
|
|
2
|
+
import type { BrowserPage } from './BrowserPage';
|
|
3
|
+
import type { IBrowserSettings, IOptionalBrowserSettings } from '../window/Window';
|
|
4
|
+
export declare interface BrowserOptions {
|
|
5
|
+
settings?: IOptionalBrowserSettings
|
|
6
|
+
console?: Console
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Browser represents an instance of a VeryHappyDOM browser
|
|
10
|
+
* Compatible with Happy DOM's Browser API
|
|
11
|
+
*/
|
|
12
|
+
export declare class Browser {
|
|
13
|
+
console: Console;
|
|
14
|
+
defaultContext: BrowserContext;
|
|
15
|
+
private _contexts: BrowserContext[];
|
|
16
|
+
private _settings: IBrowserSettings;
|
|
17
|
+
constructor(options?: BrowserOptions);
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
waitUntilComplete(): Promise<void>;
|
|
20
|
+
abort(): Promise<void>;
|
|
21
|
+
newIncognitoContext(): BrowserContext;
|
|
22
|
+
newPage(): BrowserPage;
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BrowserPage } from './BrowserPage';
|
|
2
|
+
import { CookieContainer } from './CookieContainer';
|
|
3
|
+
import type { Browser } from './Browser';
|
|
4
|
+
/**
|
|
5
|
+
* BrowserContext represents a context where data such as cache and cookies
|
|
6
|
+
* can be shared between its pages
|
|
7
|
+
* Compatible with Happy DOM's BrowserContext API
|
|
8
|
+
*/
|
|
9
|
+
export declare class BrowserContext {
|
|
10
|
+
cookieContainer: CookieContainer;
|
|
11
|
+
responseCache: Map<string, Response>;
|
|
12
|
+
preflightResponseCache: Map<string, Response>;
|
|
13
|
+
private _browser: Browser;
|
|
14
|
+
private _pages: BrowserPage[];
|
|
15
|
+
constructor(browser: Browser);
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
waitUntilComplete(): Promise<void>;
|
|
18
|
+
abort(): Promise<void>;
|
|
19
|
+
newPage(): BrowserPage;
|
|
20
|
+
_removePage(page: BrowserPage): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { VirtualDocument } from '../nodes/VirtualDocument';
|
|
2
|
+
import type { BrowserPage } from './BrowserPage';
|
|
3
|
+
/**
|
|
4
|
+
* BrowserFrame represents a browser frame
|
|
5
|
+
* Compatible with Happy DOM's BrowserFrame API
|
|
6
|
+
*/
|
|
7
|
+
export declare class BrowserFrame {
|
|
8
|
+
window: Window & { document: VirtualDocument };
|
|
9
|
+
document: VirtualDocument;
|
|
10
|
+
private _page: BrowserPage;
|
|
11
|
+
private _parentFrame: BrowserFrame | null;
|
|
12
|
+
private _childFrames: BrowserFrame[];
|
|
13
|
+
private _url: string;
|
|
14
|
+
private _content: string;
|
|
15
|
+
constructor(page: BrowserPage, parentFrame?: BrowserFrame | null);
|
|
16
|
+
waitUntilComplete(): Promise<void>;
|
|
17
|
+
waitForNavigation(): Promise<void>;
|
|
18
|
+
abort(): Promise<void>;
|
|
19
|
+
evaluate(code: string | ((...args: any[]) => any)): any;
|
|
20
|
+
goto(url: string): Promise<Response | null>;
|
|
21
|
+
goBack(): Promise<Response | null>;
|
|
22
|
+
goForward(): Promise<Response | null>;
|
|
23
|
+
goSteps(_steps: number): Promise<Response | null>;
|
|
24
|
+
reload(): Promise<Response | null>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BrowserFrame } from './BrowserFrame';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import type { BrowserContext } from './BrowserContext';
|
|
4
|
+
export declare interface IBrowserPageViewport {
|
|
5
|
+
width: number
|
|
6
|
+
height: number
|
|
7
|
+
}
|
|
8
|
+
export type PageEventType = 'console' | 'request' | 'response' | 'error' | 'load' | 'domcontentloaded'
|
|
9
|
+
export type PageEventHandler = (event: any) => void
|
|
10
|
+
/**
|
|
11
|
+
* BrowserPage represents a browser page (tab or popup window)
|
|
12
|
+
* Compatible with Happy DOM's BrowserPage API
|
|
13
|
+
*/
|
|
14
|
+
export declare class BrowserPage {
|
|
15
|
+
mainFrame: BrowserFrame;
|
|
16
|
+
console: Console;
|
|
17
|
+
virtualConsolePrinter: ((type: string, ...args: any[]) => void) | null;
|
|
18
|
+
private _context: BrowserContext;
|
|
19
|
+
private _viewport: IBrowserPageViewport;
|
|
20
|
+
private _frames: BrowserFrame[];
|
|
21
|
+
private _eventListeners: any;
|
|
22
|
+
private _requestInterceptor: any;
|
|
23
|
+
constructor(context: BrowserContext);
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
waitUntilComplete(): Promise<void>;
|
|
26
|
+
waitForNavigation(): Promise<void>;
|
|
27
|
+
abort(): Promise<void>;
|
|
28
|
+
evaluate(code: string | ((...args: any[]) => any)): any;
|
|
29
|
+
setViewport(viewport: IBrowserPageViewport): void;
|
|
30
|
+
goto(url: string): Promise<Response | null>;
|
|
31
|
+
goBack(): Promise<Response | null>;
|
|
32
|
+
goForward(): Promise<Response | null>;
|
|
33
|
+
goSteps(steps: number): Promise<Response | null>;
|
|
34
|
+
reload(): Promise<Response | null>;
|
|
35
|
+
waitForSelector(selector: string, options?: { timeout?: number, visible?: boolean }): Promise<any | null>;
|
|
36
|
+
waitForFunction(fn: ((...args: any[]) => any) | string, options?: { timeout?: number, polling?: number | 'raf' }): Promise<any>;
|
|
37
|
+
waitForTimeout(ms: number): Promise<void>;
|
|
38
|
+
click(selector: string, options?: { delay?: number, button?: 'left' | 'right' | 'middle' }): Promise<void>;
|
|
39
|
+
type(selector: string, text: string, options?: { delay?: number }): Promise<void>;
|
|
40
|
+
focus(selector: string): Promise<void>;
|
|
41
|
+
hover(selector: string): Promise<void>;
|
|
42
|
+
on(event: PageEventType, handler: PageEventHandler): void;
|
|
43
|
+
off(event: PageEventType, handler: PageEventHandler): void;
|
|
44
|
+
emit(event: PageEventType, data: any): void;
|
|
45
|
+
_emitConsole(type: string, args: any[]): void;
|
|
46
|
+
_emitRequest(request: any): void;
|
|
47
|
+
_emitResponse(response: any): void;
|
|
48
|
+
_emitError(error: Error): void;
|
|
49
|
+
dragAndDrop(source: string, target: string, options?: { delay?: number }): Promise<void>;
|
|
50
|
+
setRequestInterception(enabled: boolean): Promise<void>;
|
|
51
|
+
screenshot(options?: {
|
|
52
|
+
type?: 'png' | 'jpeg' | 'webp'
|
|
53
|
+
quality?: number
|
|
54
|
+
fullPage?: boolean
|
|
55
|
+
clip?: { x: number, y: number, width: number, height: number }
|
|
56
|
+
omitBackground?: boolean
|
|
57
|
+
encoding?: 'base64' | 'binary'
|
|
58
|
+
}): Promise<string | Buffer>;
|
|
59
|
+
pdf(options?: {
|
|
60
|
+
path?: string
|
|
61
|
+
scale?: number
|
|
62
|
+
displayHeaderFooter?: boolean
|
|
63
|
+
headerTemplate?: string
|
|
64
|
+
footerTemplate?: string
|
|
65
|
+
printBackground?: boolean
|
|
66
|
+
landscape?: boolean
|
|
67
|
+
pageRanges?: string
|
|
68
|
+
format?: 'Letter' | 'Legal' | 'Tabloid' | 'Ledger' | 'A0' | 'A1' | 'A2' | 'A3' | 'A4' | 'A5' | 'A6'
|
|
69
|
+
width?: string | number
|
|
70
|
+
height?: string | number
|
|
71
|
+
margin?: {
|
|
72
|
+
top?: string | number
|
|
73
|
+
right?: string | number
|
|
74
|
+
bottom?: string | number
|
|
75
|
+
left?: string | number
|
|
76
|
+
}
|
|
77
|
+
preferCSSPageSize?: boolean
|
|
78
|
+
}): Promise<Buffer>;
|
|
79
|
+
private _generateSVG(html: string): string;
|
|
80
|
+
private _generatePDF(html: string): string;
|
|
81
|
+
private _escapeXML(text: string): string;
|
|
82
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare interface ICookie {
|
|
2
|
+
key: string
|
|
3
|
+
value?: string
|
|
4
|
+
originURL: string
|
|
5
|
+
domain?: string
|
|
6
|
+
path?: string
|
|
7
|
+
expires?: Date
|
|
8
|
+
httpOnly?: boolean
|
|
9
|
+
secure?: boolean
|
|
10
|
+
sameSite?: CookieSameSiteEnum
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* CookieContainer manages cookies stored in memory for a BrowserContext
|
|
14
|
+
*/
|
|
15
|
+
export declare class CookieContainer {
|
|
16
|
+
private _cookies: ICookie[];
|
|
17
|
+
addCookies(cookies: ICookie[]): void;
|
|
18
|
+
getCookies(url: string, includeHttpOnly?: any): ICookie[];
|
|
19
|
+
clearCookies(): void;
|
|
20
|
+
}
|
|
21
|
+
export declare enum CookieSameSiteEnum {
|
|
22
|
+
none = 'None',
|
|
23
|
+
lax = 'Lax',
|
|
24
|
+
strict = 'Strict',
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { VirtualEvent } from './VirtualEvent';
|
|
2
|
+
export declare interface CustomEventInit {
|
|
3
|
+
bubbles?: boolean
|
|
4
|
+
cancelable?: boolean
|
|
5
|
+
detail?: any
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* CustomEvent implementation
|
|
9
|
+
* Compatible with DOM CustomEvent API
|
|
10
|
+
*/
|
|
11
|
+
export declare class CustomEvent extends VirtualEvent {
|
|
12
|
+
detail: any;
|
|
13
|
+
constructor(type: string, eventInitDict?: CustomEventInit);
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { VirtualElement } from '../nodes/VirtualElement';
|
|
2
|
+
export declare class VirtualEvent {
|
|
3
|
+
type: string;
|
|
4
|
+
target: VirtualElement | null;
|
|
5
|
+
currentTarget: VirtualElement | null;
|
|
6
|
+
bubbles: boolean;
|
|
7
|
+
cancelable: boolean;
|
|
8
|
+
defaultPrevented: any;
|
|
9
|
+
propagationStopped: any;
|
|
10
|
+
immediatePropagationStopped: any;
|
|
11
|
+
timeStamp: number;
|
|
12
|
+
constructor(type: string, options?: { bubbles?: boolean, cancelable?: boolean });
|
|
13
|
+
preventDefault(): void;
|
|
14
|
+
stopPropagation(): void;
|
|
15
|
+
stopImmediatePropagation(): void;
|
|
16
|
+
}
|