-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcorpus-utils.ts
More file actions
132 lines (118 loc) · 3.97 KB
/
corpus-utils.ts
File metadata and controls
132 lines (118 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import fs from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import type { Har as HarFile } from 'har-format'
import { parseHTML } from 'linkedom'
import { CORPUS } from './corpus/_corpus-index'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
export interface TestDOMGlobals {
Document: typeof Document
DocumentFragment: typeof DocumentFragment
document: Document
Element: typeof Element
HTMLDivElement: typeof HTMLDivElement
HTMLElement: typeof HTMLElement
HTMLMetaElement: typeof HTMLMetaElement
HTMLTextAreaElement: typeof HTMLTextAreaElement
location: Location
Node: typeof Node
Text: typeof Text
window: Window
}
export interface TestDOMContext {
cleanup: () => void
document: Document
window: Window
url: string
}
let currentDOMInstance: any = null
let originalGlobals: Partial<TestDOMGlobals> = {}
export async function setupDOM(key: keyof typeof CORPUS): Promise<TestDOMGlobals> {
const entry = CORPUS[key]
if (!entry) {
throw new Error(`Invalid corpus key: ${String(key)}`)
}
let html: string
if (entry.type === 'har') {
html = await loadRootHtmlStringFromHar(key)
} else if (entry.type === 'html') {
html = await loadHtmlStringFromHtml(key)
} else {
throw new Error(`Unsupported corpus type: ${entry.type}`)
}
const domGlobals = createDOMFromString(html, entry.url)
setupDOMFromHar(domGlobals)
return domGlobals
}
async function loadRootHtmlStringFromHar(key: keyof typeof CORPUS): Promise<string> {
const entry = CORPUS[key]
if (!entry || entry.type !== 'har') {
throw new Error(`Invalid HAR corpus key: ${String(key)}`)
}
const url = entry.url
const harPath = path.join(__dirname, 'corpus', `${String(key)}.har`)
const harContent = await fs.readFile(harPath, 'utf-8')
const harData: HarFile = JSON.parse(harContent)
const mainEntry = harData.log.entries.find((entry) => entry.request.url === url)
if (!mainEntry) {
throw new Error(`No entry found for URL: ${url} in HAR file: ${harPath}`)
}
return mainEntry.response.content.text!
}
async function loadHtmlStringFromHtml(key: keyof typeof CORPUS): Promise<string> {
const entry = CORPUS[key]
if (!entry || entry.type !== 'html') {
throw new Error(`Invalid HTML corpus key: ${String(key)}`)
}
const htmlPath = path.join(__dirname, 'corpus', `${String(key)}.html`)
return await fs.readFile(htmlPath, 'utf-8')
}
function createDOMFromString(html: string, url: string): TestDOMGlobals {
const dom = parseHTML(html)
return {
Document: dom.Document,
DocumentFragment: dom.DocumentFragment,
document: dom.document,
Element: dom.Element,
HTMLDivElement: dom.HTMLDivElement,
HTMLElement: dom.HTMLElement,
HTMLMetaElement: dom.HTMLMetaElement,
HTMLTextAreaElement: dom.HTMLTextAreaElement,
location: new URL(url) as any,
Node: dom.Node,
Text: dom.Text,
window: {
...dom.window,
location: new URL(url),
} as any,
}
}
function setupDOMFromHar(domGlobals: TestDOMGlobals): void {
// Store original globals for cleanup
originalGlobals = {
Document: (globalThis as any).Document,
DocumentFragment: (globalThis as any).DocumentFragment,
document: (globalThis as any).document,
Element: (globalThis as any).Element,
HTMLDivElement: (globalThis as any).HTMLDivElement,
HTMLElement: (globalThis as any).HTMLElement,
HTMLMetaElement: (globalThis as any).HTMLMetaElement,
HTMLTextAreaElement: (globalThis as any).HTMLTextAreaElement,
location: (globalThis as any).location,
Node: (globalThis as any).Node,
Text: (globalThis as any).Text,
window: (globalThis as any).window,
}
// Set new globals
Object.assign(globalThis, domGlobals)
currentDOMInstance = domGlobals
}
export function cleanupDOM(): void {
if (currentDOMInstance) {
// Reset globals to original values
Object.assign(globalThis, originalGlobals)
// Clear references
currentDOMInstance = null
originalGlobals = {}
}
}