cyperful 0.1.10 → 0.3.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.
- checksums.yaml +4 -4
- data/lib/cyperful/driver.rb +71 -33
- data/lib/cyperful/framework_helper.rb +7 -0
- data/lib/cyperful/framework_injections.rb +22 -28
- data/lib/cyperful/logger.rb +14 -0
- data/lib/cyperful/minitest.rb +30 -0
- data/lib/cyperful/rspec.rb +24 -0
- data/lib/cyperful/test_parser.rb +78 -14
- data/lib/cyperful/ui_server.rb +0 -9
- data/lib/cyperful.rb +28 -1
- data/public/assets/index-DQa6Blo_.js +51 -0
- data/public/assets/index-DqywWqA7.css +1 -0
- data/public/assets/syntax-highlighter-worker-BezFv5DT.js +12 -0
- data/public/frame-agent.js +169 -104
- data/public/index.html +2 -2
- metadata +26 -8
- data/public/assets/index-CrBQcYdq.js +0 -42
- data/public/assets/index-Uj6YFMhM.css +0 -1
- data/public/assets/syntax-highlighter-worker-Cumko8SL.js +0 -2798
data/public/frame-agent.js
CHANGED
@@ -1,123 +1,188 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
1
|
+
const m = __CYPERFUL_CONFIG__;
|
2
|
+
function L() {
|
3
|
+
if (!m)
|
4
|
+
throw new Error("Cyperful Agent config not initialized");
|
5
|
+
return m;
|
6
|
+
}
|
7
|
+
let _ = 0;
|
8
|
+
const p = (r, t, c = null) => {
|
9
|
+
const { CYPERFUL_ORIGIN: s } = L();
|
10
|
+
let n = null;
|
11
|
+
try {
|
12
|
+
const e = Date.now(), i = `${e}-${_++}`;
|
13
|
+
if ("url" in t && t.url != null)
|
14
|
+
try {
|
15
|
+
const o = new URL(t.url, window.location.origin);
|
16
|
+
if (o.origin === s) return null;
|
17
|
+
o.origin === window.location.origin && (t.url = o.pathname + o.search + o.hash);
|
18
|
+
} catch {
|
19
|
+
}
|
20
|
+
n = {
|
21
|
+
type: r,
|
22
|
+
data: t,
|
23
|
+
id: i,
|
24
|
+
timestamp: e,
|
25
|
+
start_id: c ? c.id : void 0
|
26
|
+
}, window.parent.postMessage(n, s);
|
27
|
+
} catch {
|
11
28
|
}
|
12
|
-
|
13
|
-
|
14
|
-
|
29
|
+
return n;
|
30
|
+
};
|
31
|
+
function R(r) {
|
32
|
+
try {
|
33
|
+
if (typeof r == "string") return JSON.parse(r);
|
34
|
+
} catch {
|
35
|
+
return r;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
function y(r) {
|
39
|
+
const t = {};
|
40
|
+
for (const [c, s] of r.entries())
|
41
|
+
s instanceof Blob ? t[c] = `[[ Blob: ${s.size} bytes ]]` : t[c] = s.toString();
|
42
|
+
return t;
|
43
|
+
}
|
44
|
+
const S = () => {
|
45
|
+
const r = window.fetch;
|
46
|
+
window.fetch = (...t) => {
|
47
|
+
var g;
|
48
|
+
const [c, s = {}] = typeof t[0] == "string" || t[0] instanceof URL ? [t[0], t[1]] : [t[0].url, t[0]], n = ((g = s.method) == null ? void 0 : g.toUpperCase()) ?? "GET", e = s.body, o = new Headers(s.headers).get("content-type") || void 0;
|
49
|
+
let d;
|
15
50
|
try {
|
16
|
-
|
17
|
-
if ("url" in e && e.url != null)
|
18
|
-
try {
|
19
|
-
const o = new URL(e.url, window.location.origin);
|
20
|
-
if (o.origin === u)
|
21
|
-
return null;
|
22
|
-
o.origin === window.location.origin && (e.url = o.pathname + o.search + o.hash);
|
23
|
-
} catch {
|
24
|
-
}
|
25
|
-
i = {
|
26
|
-
type: t,
|
27
|
-
data: e,
|
28
|
-
id: c,
|
29
|
-
timestamp: r,
|
30
|
-
start_id: n ? n.id : void 0
|
31
|
-
}, window.parent.postMessage(i, u);
|
51
|
+
d = e instanceof FormData ? y(e) : o != null && o.match(/[+/]json\b/) ? R(e) : e;
|
32
52
|
} catch {
|
33
53
|
}
|
34
|
-
|
54
|
+
const a = p("fetch", {
|
55
|
+
method: n,
|
56
|
+
url: c.toString(),
|
57
|
+
body: d,
|
58
|
+
bodyType: o
|
59
|
+
}), u = r(...t);
|
60
|
+
return u.then(async (h) => {
|
61
|
+
const l = h.headers.get("content-type") || void 0;
|
62
|
+
let f;
|
63
|
+
try {
|
64
|
+
const w = h.clone();
|
65
|
+
l != null && l.match(/\bform-data\b/) && (f = y(await w.formData())), l != null && l.match(/[+/]json\b/) ? f = await w.json() : l != null && l.match(/\btext[+/]/) ? f = await w.text() : f = `[[ Unhandled content-type: ${l || "<empty>"} ]]`;
|
66
|
+
} catch {
|
67
|
+
}
|
68
|
+
a && p(
|
69
|
+
"fetch:finished",
|
70
|
+
{
|
71
|
+
status: h.status,
|
72
|
+
responseType: l,
|
73
|
+
response: f
|
74
|
+
},
|
75
|
+
a
|
76
|
+
);
|
77
|
+
}).catch((h) => {
|
78
|
+
a && p(
|
79
|
+
"fetch:finished",
|
80
|
+
{
|
81
|
+
status: 0,
|
82
|
+
response: `[caught error] ${h.message || "Unknown error"}`
|
83
|
+
},
|
84
|
+
a
|
85
|
+
);
|
86
|
+
}), u;
|
35
87
|
};
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
s("global_error", { message: t.error.toString() });
|
51
|
-
}), window.addEventListener("unhandledrejection", (t) => {
|
52
|
-
s("unhandledrejection", { message: t.reason.toString() });
|
53
|
-
});
|
54
|
-
function w(t) {
|
88
|
+
}, q = () => {
|
89
|
+
const r = window.XMLHttpRequest.prototype.open, t = window.XMLHttpRequest.prototype.send, c = window.XMLHttpRequest.prototype.setRequestHeader;
|
90
|
+
window.XMLHttpRequest.prototype.open = function(...n) {
|
91
|
+
return this._requestMeta = {
|
92
|
+
method: n[0],
|
93
|
+
url: n[1].toString(),
|
94
|
+
headers: {}
|
95
|
+
}, r.apply(this, n);
|
96
|
+
}, window.XMLHttpRequest.prototype.setRequestHeader = function(n, e) {
|
97
|
+
const i = this._requestMeta;
|
98
|
+
return i && (i.headers[n.toLowerCase()] = e), c.apply(this, [n, e]);
|
99
|
+
}, window.XMLHttpRequest.prototype.send = function(n) {
|
100
|
+
const e = this._requestMeta, i = e == null ? void 0 : e.headers["content-type"];
|
101
|
+
let o;
|
55
102
|
try {
|
56
|
-
|
57
|
-
return JSON.parse(t);
|
103
|
+
o = n instanceof FormData ? y(n) : i != null && i.match(/[+/]json\b/) ? R(n) : n;
|
58
104
|
} catch {
|
59
|
-
return t;
|
60
105
|
}
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
return t.addEventListener("load", () => {
|
78
|
-
o && s(
|
79
|
-
"xhr:finished",
|
80
|
-
{ status: t.status, response: t.response },
|
81
|
-
o
|
82
|
-
);
|
83
|
-
}), e.apply(this, n);
|
84
|
-
}, t;
|
85
|
-
}
|
86
|
-
window.XMLHttpRequest = m;
|
87
|
-
const L = window.fetch;
|
88
|
-
window.fetch = (...t) => {
|
89
|
-
const [e, n = {}] = typeof t[0] == "string" || t[0] instanceof URL ? [t[0], t[1]] : [t[0].url, t[0]], i = n.method ?? "GET", r = n.body, c = n.headers || {}, o = c["content-type"] || c["Content-Type"] || void 0, R = r instanceof FormData ? g(r) : o != null && o.includes("application/json") ? w(r) : r, p = s("fetch", {
|
90
|
-
method: i,
|
91
|
-
url: e.toString(),
|
92
|
-
body: R,
|
93
|
-
bodyType: o
|
94
|
-
}), h = L(...t);
|
95
|
-
return h.then(async (l) => {
|
96
|
-
const a = l.headers.get("content-type") || "", v = a.includes("application/json") ? await l.clone().json() : a.includes("text/") ? await l.clone().text() : `[[ Unhandled content-type: ${a || "<empty>"} ]]`;
|
97
|
-
p && s(
|
98
|
-
"fetch:finished",
|
106
|
+
const d = e ? p("xhr", {
|
107
|
+
method: e.method,
|
108
|
+
url: e.url,
|
109
|
+
body: o,
|
110
|
+
bodyType: i
|
111
|
+
}) : null;
|
112
|
+
return this.addEventListener("load", async () => {
|
113
|
+
if (!d) return;
|
114
|
+
const a = this.getResponseHeader("content-type") || void 0;
|
115
|
+
let u;
|
116
|
+
try {
|
117
|
+
u = a != null && a.match(/[+/]json\b/) ? await this.response.clone().json() : a != null && a.match(/\btext[+/]/) ? await this.response.clone().text() : `[[ Unhandled content-type: ${a || "<empty>"} ]]`;
|
118
|
+
} catch {
|
119
|
+
}
|
120
|
+
p(
|
121
|
+
"xhr:finished",
|
99
122
|
{
|
100
|
-
status:
|
101
|
-
|
102
|
-
|
123
|
+
status: this.status,
|
124
|
+
response: u,
|
125
|
+
responseType: a
|
103
126
|
},
|
104
|
-
|
127
|
+
d
|
105
128
|
);
|
106
|
-
}).
|
107
|
-
|
129
|
+
}), this.addEventListener("error", () => {
|
130
|
+
d && p(
|
131
|
+
"xhr:finished",
|
132
|
+
{
|
133
|
+
status: 0,
|
134
|
+
response: `[caught error] ${this.status ?? 0} - ${this.statusText || "Unknown error"}`
|
135
|
+
},
|
136
|
+
d
|
137
|
+
);
|
138
|
+
}), t.apply(this, [n]);
|
108
139
|
};
|
109
|
-
|
110
|
-
|
111
|
-
|
140
|
+
}, H = () => {
|
141
|
+
if (window.__cyperfulAgentInitialized) return;
|
142
|
+
window.__cyperfulAgentInitialized = !0;
|
143
|
+
const r = console.log, t = (...e) => r("[Cyperful Agent]", ...e);
|
144
|
+
t("Loading...");
|
145
|
+
const { CYPERFUL_ORIGIN: c } = L();
|
146
|
+
if (window.location.origin === c) {
|
147
|
+
t("Ignoring parent frame (Why are we here?)");
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
S(), q(), window.addEventListener("error", (e) => {
|
151
|
+
p("global_error", { message: e.error.toString() });
|
152
|
+
}), window.addEventListener("unhandledrejection", (e) => {
|
153
|
+
p("unhandledrejection", { message: e.reason.toString() });
|
154
|
+
});
|
155
|
+
const s = history.pushState;
|
156
|
+
history.pushState = (...e) => {
|
157
|
+
s.apply(history, e), p("client_navigate", {
|
112
158
|
url: location.href,
|
113
159
|
replace: !1
|
114
160
|
});
|
115
161
|
};
|
116
|
-
const
|
117
|
-
history.replaceState = (...
|
118
|
-
|
162
|
+
const n = history.replaceState;
|
163
|
+
history.replaceState = (...e) => {
|
164
|
+
n.apply(history, e), p("client_navigate", {
|
119
165
|
url: location.href,
|
120
166
|
replace: !0
|
121
167
|
});
|
122
|
-
}
|
123
|
-
|
168
|
+
};
|
169
|
+
for (const e of [
|
170
|
+
"log",
|
171
|
+
"error",
|
172
|
+
"warn",
|
173
|
+
"info",
|
174
|
+
"dir",
|
175
|
+
"debug"
|
176
|
+
]) {
|
177
|
+
const i = console[e];
|
178
|
+
i && (console[e] = (...o) => {
|
179
|
+
i.apply(console, o), p("log", { level: e, args: o });
|
180
|
+
});
|
181
|
+
}
|
182
|
+
t("Loaded.");
|
183
|
+
};
|
184
|
+
try {
|
185
|
+
H();
|
186
|
+
} catch (r) {
|
187
|
+
console.error("Cyperful Agent failed to load", r);
|
188
|
+
}
|
data/public/index.html
CHANGED
@@ -5,8 +5,8 @@
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
6
6
|
<link rel="icon" href="/assets/favicon-DMdBZQlK.ico" />
|
7
7
|
<title>Cyperful</title>
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
8
|
+
<script type="module" crossorigin src="/assets/index-DQa6Blo_.js"></script>
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DqywWqA7.css">
|
10
10
|
</head>
|
11
11
|
<body class="bg-stone-900 text-slate-100">
|
12
12
|
<div id="root"></div>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cyperful
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wyatt Ades
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: capybara
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parser
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: listen
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,14 +58,14 @@ dependencies:
|
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.0.
|
61
|
+
version: 0.0.4
|
48
62
|
type: :runtime
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
66
|
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.0.
|
68
|
+
version: 0.0.4
|
55
69
|
description:
|
56
70
|
email:
|
57
71
|
executables: []
|
@@ -61,14 +75,18 @@ files:
|
|
61
75
|
- lib/cyperful.rb
|
62
76
|
- lib/cyperful/commands.rb
|
63
77
|
- lib/cyperful/driver.rb
|
78
|
+
- lib/cyperful/framework_helper.rb
|
64
79
|
- lib/cyperful/framework_injections.rb
|
80
|
+
- lib/cyperful/logger.rb
|
81
|
+
- lib/cyperful/minitest.rb
|
65
82
|
- lib/cyperful/railtie.rb
|
83
|
+
- lib/cyperful/rspec.rb
|
66
84
|
- lib/cyperful/test_parser.rb
|
67
85
|
- lib/cyperful/ui_server.rb
|
68
86
|
- public/assets/favicon-DMdBZQlK.ico
|
69
|
-
- public/assets/index-
|
70
|
-
- public/assets/index-
|
71
|
-
- public/assets/syntax-highlighter-worker-
|
87
|
+
- public/assets/index-DQa6Blo_.js
|
88
|
+
- public/assets/index-DqywWqA7.css
|
89
|
+
- public/assets/syntax-highlighter-worker-BezFv5DT.js
|
72
90
|
- public/frame-agent.js
|
73
91
|
- public/index.html
|
74
92
|
homepage: https://github.com/stepful/cyperful
|
@@ -90,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
90
108
|
- !ruby/object:Gem::Version
|
91
109
|
version: '0'
|
92
110
|
requirements: []
|
93
|
-
rubygems_version: 3.5.
|
111
|
+
rubygems_version: 3.5.16
|
94
112
|
signing_key:
|
95
113
|
specification_version: 4
|
96
114
|
summary: Interactive test debugger for Capybara tests
|