@wdio/devtools-script 0.0.0 → 1.0.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/script.js +53 -34
- package/package.json +1 -1
- package/src/collector.ts +7 -7
- package/src/collectors/consoleLogs.ts +3 -3
- package/src/index.ts +63 -32
- package/src/logger.ts +3 -3
- package/src/utils.ts +30 -19
- package/tsconfig.json +1 -1
- package/types.d.ts +3 -1
package/dist/script.js
CHANGED
|
@@ -5702,7 +5702,9 @@ function Ce(e) {
|
|
|
5702
5702
|
for (const d of s || [])
|
|
5703
5703
|
t[d.name] = d.value;
|
|
5704
5704
|
try {
|
|
5705
|
-
return se(
|
|
5705
|
+
return se(
|
|
5706
|
+
V(c, t, ...(a || []).map((d) => Ce(d)))
|
|
5707
|
+
);
|
|
5706
5708
|
} catch (d) {
|
|
5707
5709
|
return se(V("div", { class: "parseNode" }, d.stack));
|
|
5708
5710
|
}
|
|
@@ -5739,14 +5741,15 @@ async function is() {
|
|
|
5739
5741
|
let ye = 0;
|
|
5740
5742
|
function we(e) {
|
|
5741
5743
|
if (typeof e.querySelectorAll != "function") {
|
|
5742
|
-
x(
|
|
5744
|
+
x(
|
|
5745
|
+
"assignRef: elem has no querySelectorAll",
|
|
5746
|
+
e.nodeType || e.nodeName || e.textContent || Object.keys(e)
|
|
5747
|
+
);
|
|
5743
5748
|
return;
|
|
5744
5749
|
}
|
|
5745
|
-
e.hasAttribute("data-wdio-ref") || e.setAttribute("data-wdio-ref", `${++ye}`), Array.from(e.querySelectorAll("*")).forEach(
|
|
5746
|
-
(
|
|
5747
|
-
|
|
5748
|
-
}
|
|
5749
|
-
);
|
|
5750
|
+
e.hasAttribute("data-wdio-ref") || e.setAttribute("data-wdio-ref", `${++ye}`), Array.from(e.querySelectorAll("*")).forEach((t) => {
|
|
5751
|
+
t.setAttribute("data-wdio-ref", `${++ye}`);
|
|
5752
|
+
});
|
|
5750
5753
|
}
|
|
5751
5754
|
function Z(e) {
|
|
5752
5755
|
return !e || !e.getAttribute ? null : e.getAttribute("data-wdio-ref");
|
|
@@ -5808,38 +5811,54 @@ const $ = window.wdioTraceCollector = new os();
|
|
|
5808
5811
|
try {
|
|
5809
5812
|
x("waiting for body to render"), await is(), x("body rendered"), we(document.documentElement), x("applied wdio ref ids");
|
|
5810
5813
|
const e = Date.now();
|
|
5811
|
-
$.captureMutation([
|
|
5812
|
-
|
|
5813
|
-
|
|
5814
|
-
|
|
5815
|
-
|
|
5816
|
-
|
|
5817
|
-
|
|
5814
|
+
$.captureMutation([
|
|
5815
|
+
{
|
|
5816
|
+
type: "childList",
|
|
5817
|
+
url: document.location.href,
|
|
5818
|
+
timestamp: e,
|
|
5819
|
+
addedNodes: [ss(document.documentElement)],
|
|
5820
|
+
removedNodes: []
|
|
5821
|
+
}
|
|
5822
|
+
]), x("added initial page structure");
|
|
5818
5823
|
const t = { attributes: !0, childList: !0, subtree: !0 };
|
|
5819
5824
|
new MutationObserver((s) => {
|
|
5820
5825
|
const c = Date.now(), d = s.filter((h) => h.attributeName !== "data-wdio-ref");
|
|
5821
5826
|
x(`observed ${d.length} mutations`);
|
|
5822
5827
|
try {
|
|
5823
|
-
$.captureMutation(
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5828
|
+
$.captureMutation(
|
|
5829
|
+
d.map(
|
|
5830
|
+
({
|
|
5831
|
+
target: h,
|
|
5832
|
+
addedNodes: f,
|
|
5833
|
+
removedNodes: _,
|
|
5834
|
+
type: A,
|
|
5835
|
+
attributeName: O,
|
|
5836
|
+
attributeNamespace: U,
|
|
5837
|
+
previousSibling: R,
|
|
5838
|
+
nextSibling: Oe,
|
|
5839
|
+
oldValue: mt
|
|
5840
|
+
}) => {
|
|
5841
|
+
const bt = Array.from(f).map((j) => (we(j), rs(j))), At = Array.from(_).map((j) => Z(j)), Nt = Z(h), It = R ? Z(R) : null, Ct = Oe ? Z(Oe) : null;
|
|
5842
|
+
let Se;
|
|
5843
|
+
A === "attributes" && (Se = h.getAttribute(O) || "");
|
|
5844
|
+
let Le;
|
|
5845
|
+
return A === "characterData" && (Le = h.textContent || ""), x(`added mutation: ${A}`), {
|
|
5846
|
+
type: A,
|
|
5847
|
+
attributeName: O,
|
|
5848
|
+
attributeNamespace: U,
|
|
5849
|
+
oldValue: mt,
|
|
5850
|
+
addedNodes: bt,
|
|
5851
|
+
target: Nt,
|
|
5852
|
+
removedNodes: At,
|
|
5853
|
+
previousSibling: It,
|
|
5854
|
+
nextSibling: Ct,
|
|
5855
|
+
timestamp: c,
|
|
5856
|
+
attributeValue: Se,
|
|
5857
|
+
newTextContent: Le
|
|
5858
|
+
};
|
|
5859
|
+
}
|
|
5860
|
+
)
|
|
5861
|
+
);
|
|
5843
5862
|
} catch (h) {
|
|
5844
5863
|
$.captureError(h);
|
|
5845
5864
|
}
|
package/package.json
CHANGED
package/src/collector.ts
CHANGED
|
@@ -10,33 +10,33 @@ class DataCollector {
|
|
|
10
10
|
#mutations: TraceMutation[] = []
|
|
11
11
|
#consoleLogs = new ConsoleLogCollector()
|
|
12
12
|
|
|
13
|
-
captureError
|
|
13
|
+
captureError(err: Error) {
|
|
14
14
|
const error = err.stack || err.message
|
|
15
15
|
this.#errors.push(error)
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
captureMutation
|
|
18
|
+
captureMutation(mutations: TraceMutation[]) {
|
|
19
19
|
this.#mutations.push(...mutations)
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
reset
|
|
22
|
+
reset() {
|
|
23
23
|
this.#errors = []
|
|
24
24
|
this.#mutations = []
|
|
25
25
|
this.#consoleLogs.clear()
|
|
26
26
|
clearLogs()
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
getMetadata
|
|
29
|
+
getMetadata() {
|
|
30
30
|
return this.#metadata
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
getTraceData
|
|
33
|
+
getTraceData() {
|
|
34
34
|
const data = {
|
|
35
35
|
errors: this.#errors,
|
|
36
36
|
mutations: this.#mutations,
|
|
37
37
|
consoleLogs: this.#consoleLogs.getArtifacts(),
|
|
38
38
|
traceLogs: getLogs(),
|
|
39
|
-
metadata: this.getMetadata()
|
|
39
|
+
metadata: this.getMetadata()
|
|
40
40
|
} as const
|
|
41
41
|
this.reset()
|
|
42
42
|
return data
|
|
@@ -44,4 +44,4 @@ class DataCollector {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export type DataCollectorType = DataCollector
|
|
47
|
-
export const collector = window.wdioTraceCollector = new DataCollector()
|
|
47
|
+
export const collector = (window.wdioTraceCollector = new DataCollector())
|
|
@@ -9,11 +9,11 @@ export interface ConsoleLogs {
|
|
|
9
9
|
|
|
10
10
|
export class ConsoleLogCollector implements Collector<ConsoleLogs> {
|
|
11
11
|
#logs: ConsoleLogs[] = []
|
|
12
|
-
constructor
|
|
12
|
+
constructor() {
|
|
13
13
|
consoleMethods.forEach(this.#consolePatch.bind(this))
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
getArtifacts
|
|
16
|
+
getArtifacts() {
|
|
17
17
|
return this.#logs
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -21,7 +21,7 @@ export class ConsoleLogCollector implements Collector<ConsoleLogs> {
|
|
|
21
21
|
this.#logs = []
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
#consolePatch
|
|
24
|
+
#consolePatch(type: (typeof consoleMethods)[number]) {
|
|
25
25
|
const orig = console[type]
|
|
26
26
|
console[type] = (...args) => {
|
|
27
27
|
this.#logs.push({
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
waitForBody,
|
|
3
|
+
parseFragment,
|
|
4
|
+
parseDocument,
|
|
5
|
+
getRef,
|
|
6
|
+
assignRef
|
|
7
|
+
} from './utils.js'
|
|
2
8
|
import { log } from './logger.js'
|
|
3
9
|
import { collector } from './collector.js'
|
|
4
10
|
|
|
@@ -11,13 +17,15 @@ try {
|
|
|
11
17
|
log('applied wdio ref ids')
|
|
12
18
|
|
|
13
19
|
const timestamp = Date.now()
|
|
14
|
-
collector.captureMutation([
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
collector.captureMutation([
|
|
21
|
+
{
|
|
22
|
+
type: 'childList',
|
|
23
|
+
url: document.location.href,
|
|
24
|
+
timestamp,
|
|
25
|
+
addedNodes: [parseDocument(document.documentElement)],
|
|
26
|
+
removedNodes: []
|
|
27
|
+
}
|
|
28
|
+
])
|
|
21
29
|
log('added initial page structure')
|
|
22
30
|
|
|
23
31
|
const config = { attributes: true, childList: true, subtree: true }
|
|
@@ -27,33 +35,56 @@ try {
|
|
|
27
35
|
|
|
28
36
|
log(`observed ${mutationList.length} mutations`)
|
|
29
37
|
try {
|
|
30
|
-
collector.captureMutation(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
38
|
+
collector.captureMutation(
|
|
39
|
+
mutationList.map(
|
|
40
|
+
({
|
|
41
|
+
target: t,
|
|
42
|
+
addedNodes: an,
|
|
43
|
+
removedNodes: rn,
|
|
44
|
+
type,
|
|
45
|
+
attributeName,
|
|
46
|
+
attributeNamespace,
|
|
47
|
+
previousSibling: ps,
|
|
48
|
+
nextSibling: ns,
|
|
49
|
+
oldValue
|
|
50
|
+
}) => {
|
|
51
|
+
const addedNodes = Array.from(an).map((node) => {
|
|
52
|
+
assignRef(node as Element)
|
|
53
|
+
return parseFragment(node as Element)
|
|
54
|
+
})
|
|
35
55
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
56
|
+
const removedNodes = Array.from(rn).map((node) => getRef(node))
|
|
57
|
+
const target = getRef(t)
|
|
58
|
+
const previousSibling = ps ? getRef(ps) : null
|
|
59
|
+
const nextSibling = ns ? getRef(ns) : null
|
|
40
60
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
61
|
+
let attributeValue: string | undefined
|
|
62
|
+
if (type === 'attributes') {
|
|
63
|
+
attributeValue = (t as Element).getAttribute(attributeName!) || ''
|
|
64
|
+
}
|
|
65
|
+
let newTextContent: string | undefined
|
|
66
|
+
if (type === 'characterData') {
|
|
67
|
+
newTextContent = (t as Element).textContent || ''
|
|
68
|
+
}
|
|
49
69
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
70
|
+
log(`added mutation: ${type}`)
|
|
71
|
+
return {
|
|
72
|
+
type,
|
|
73
|
+
attributeName,
|
|
74
|
+
attributeNamespace,
|
|
75
|
+
oldValue,
|
|
76
|
+
addedNodes,
|
|
77
|
+
target,
|
|
78
|
+
removedNodes,
|
|
79
|
+
previousSibling,
|
|
80
|
+
nextSibling,
|
|
81
|
+
timestamp,
|
|
82
|
+
attributeValue,
|
|
83
|
+
newTextContent
|
|
84
|
+
} as TraceMutation
|
|
85
|
+
}
|
|
86
|
+
)
|
|
87
|
+
)
|
|
57
88
|
} catch (err: any) {
|
|
58
89
|
collector.captureError(err)
|
|
59
90
|
}
|
package/src/logger.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
let logs: string[] = []
|
|
2
2
|
|
|
3
|
-
export function log
|
|
3
|
+
export function log(...args: any[]) {
|
|
4
4
|
logs.push(args.map((a) => JSON.stringify(a)).join(' '))
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export function getLogs
|
|
7
|
+
export function getLogs() {
|
|
8
8
|
return logs
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export function clearLogs
|
|
11
|
+
export function clearLogs() {
|
|
12
12
|
logs = []
|
|
13
13
|
}
|
package/src/utils.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
parse,
|
|
3
|
+
parseFragment as parseFragmentImport,
|
|
4
|
+
type DefaultTreeAdapterMap
|
|
5
|
+
} from 'parse5'
|
|
2
6
|
import { h } from 'htm/preact'
|
|
3
7
|
import type { SimplifiedVNode } from '../types.ts'
|
|
4
8
|
|
|
@@ -10,12 +14,14 @@ export type vElement = DefaultTreeAdapterMap['element']
|
|
|
10
14
|
export type vText = DefaultTreeAdapterMap['textNode']
|
|
11
15
|
export type vChildNode = DefaultTreeAdapterMap['childNode']
|
|
12
16
|
|
|
13
|
-
function createVNode
|
|
17
|
+
function createVNode(elem: any) {
|
|
14
18
|
const { type, props } = elem
|
|
15
19
|
return { type, props } as SimplifiedVNode
|
|
16
20
|
}
|
|
17
21
|
|
|
18
|
-
export function parseNode
|
|
22
|
+
export function parseNode(
|
|
23
|
+
fragment: vFragment | vComment | vText | vChildNode
|
|
24
|
+
): SimplifiedVNode | string {
|
|
19
25
|
const props: Record<string, any> = {}
|
|
20
26
|
|
|
21
27
|
if (fragment.nodeName === '#comment') {
|
|
@@ -26,18 +32,20 @@ export function parseNode (fragment: vFragment | vComment | vText | vChildNode):
|
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
const { childNodes, attrs, tagName } = fragment as vElement
|
|
29
|
-
for (const p of
|
|
30
|
-
|
|
35
|
+
for (const p of attrs || []) {
|
|
36
|
+
props[p.name] = p.value
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
try {
|
|
34
|
-
return createVNode(
|
|
40
|
+
return createVNode(
|
|
41
|
+
h(tagName, props, ...(childNodes || []).map((cn) => parseNode(cn))) as any
|
|
42
|
+
)
|
|
35
43
|
} catch (err: any) {
|
|
36
44
|
return createVNode(h('div', { class: 'parseNode' }, err.stack))
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
export function parseDocument
|
|
48
|
+
export function parseDocument(node: HTMLElement) {
|
|
41
49
|
try {
|
|
42
50
|
const fragment = parse(node.outerHTML)
|
|
43
51
|
return parseNode(fragment.childNodes[0])
|
|
@@ -46,7 +54,7 @@ export function parseDocument (node: HTMLElement) {
|
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
|
|
49
|
-
export function parseFragment
|
|
57
|
+
export function parseFragment(node: Element) {
|
|
50
58
|
try {
|
|
51
59
|
const fragment = parseFragmentImport(node.outerHTML)
|
|
52
60
|
return parseNode(fragment)
|
|
@@ -55,7 +63,7 @@ export function parseFragment (node: Element) {
|
|
|
55
63
|
}
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
export async function waitForBody
|
|
66
|
+
export async function waitForBody() {
|
|
59
67
|
let raf = 0
|
|
60
68
|
let resolve: () => void
|
|
61
69
|
let reject: (err: Error) => void
|
|
@@ -69,7 +77,7 @@ export async function waitForBody () {
|
|
|
69
77
|
10000
|
|
70
78
|
)
|
|
71
79
|
|
|
72
|
-
function run
|
|
80
|
+
function run() {
|
|
73
81
|
if (!document.body) {
|
|
74
82
|
return
|
|
75
83
|
}
|
|
@@ -84,12 +92,15 @@ export async function waitForBody () {
|
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
let refId = 0
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
export function assignRef
|
|
95
|
+
/**
|
|
96
|
+
* assign a uid to each element so we can reference it later in the vdom
|
|
97
|
+
*/
|
|
98
|
+
export function assignRef(elem: Element) {
|
|
91
99
|
if (typeof elem.querySelectorAll !== 'function') {
|
|
92
|
-
log(
|
|
100
|
+
log(
|
|
101
|
+
'assignRef: elem has no querySelectorAll',
|
|
102
|
+
elem.nodeType || elem.nodeName || elem.textContent || Object.keys(elem)
|
|
103
|
+
)
|
|
93
104
|
return
|
|
94
105
|
}
|
|
95
106
|
|
|
@@ -97,14 +108,14 @@ export function assignRef (elem: Element) {
|
|
|
97
108
|
elem.setAttribute('data-wdio-ref', `${++refId}`)
|
|
98
109
|
}
|
|
99
110
|
|
|
100
|
-
Array.from(elem.querySelectorAll('*')).forEach(
|
|
101
|
-
|
|
111
|
+
Array.from(elem.querySelectorAll('*')).forEach((el) => {
|
|
112
|
+
el.setAttribute('data-wdio-ref', `${++refId}`)
|
|
113
|
+
})
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
export function getRef
|
|
116
|
+
export function getRef(elem: Node) {
|
|
105
117
|
if (!elem || !(elem as Element).getAttribute) {
|
|
106
118
|
return null
|
|
107
119
|
}
|
|
108
120
|
return (elem as Element).getAttribute('data-wdio-ref')
|
|
109
121
|
}
|
|
110
|
-
|
package/tsconfig.json
CHANGED
package/types.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ export interface TraceMetadata {
|
|
|
8
8
|
|
|
9
9
|
export interface SimplifiedVNode {
|
|
10
10
|
type: string
|
|
11
|
-
props: Record<string, string> & {
|
|
11
|
+
props: Record<string, string> & {
|
|
12
|
+
children?: SimplifiedVNode | SimplifiedVNode[]
|
|
13
|
+
}
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
declare global {
|