1use serde::Deserialize;
9use serde_json::{Map, Value};
10
11#[derive(Debug, Clone)]
15pub struct RawEvent {
16 raw: Map<String, Value>,
17}
18
19impl RawEvent {
20 pub(crate) fn new(raw: Map<String, Value>) -> Self {
21 Self { raw }
22 }
23
24 pub fn kind(&self) -> Option<&str> {
31 self.raw.get("type").and_then(|v| v.as_str())
32 }
33
34 pub fn as_value(&self) -> &Map<String, Value> {
36 &self.raw
37 }
38
39 pub fn into_value(self) -> Value {
41 Value::Object(self.raw)
42 }
43
44 pub fn into_typed(self) -> TraceEvent {
49 match serde_json::from_value::<TypedEnum>(Value::Object(self.raw.clone())) {
53 Ok(t) => t.into(),
54 Err(_) => TraceEvent::Unknown(self),
55 }
56 }
57}
58
59#[derive(Debug, Clone)]
63pub enum TraceEvent {
64 ContextOptions(ContextOptions),
65 Before(BeforeEvent),
66 Input(InputEvent),
67 Log(LogEvent),
68 After(AfterEvent),
69 Console(ConsoleEvent),
70 Event(SystemEvent),
71 FrameSnapshot(FrameSnapshotEvent),
72 ScreencastFrame(ScreencastFrameEvent),
73 Unknown(RawEvent),
76}
77
78#[derive(Deserialize)]
81#[serde(tag = "type", rename_all = "kebab-case")]
82enum TypedEnum {
83 ContextOptions(ContextOptions),
84 Before(BeforeEvent),
85 Input(InputEvent),
86 Log(LogEvent),
87 After(AfterEvent),
88 Console(ConsoleEvent),
89 Event(SystemEvent),
90 FrameSnapshot(FrameSnapshotEvent),
91 ScreencastFrame(ScreencastFrameEvent),
92}
93
94impl From<TypedEnum> for TraceEvent {
95 fn from(t: TypedEnum) -> Self {
96 match t {
97 TypedEnum::ContextOptions(c) => TraceEvent::ContextOptions(c),
98 TypedEnum::Before(b) => TraceEvent::Before(b),
99 TypedEnum::Input(i) => TraceEvent::Input(i),
100 TypedEnum::Log(l) => TraceEvent::Log(l),
101 TypedEnum::After(a) => TraceEvent::After(a),
102 TypedEnum::Console(c) => TraceEvent::Console(c),
103 TypedEnum::Event(e) => TraceEvent::Event(e),
104 TypedEnum::FrameSnapshot(f) => TraceEvent::FrameSnapshot(f),
105 TypedEnum::ScreencastFrame(s) => TraceEvent::ScreencastFrame(s),
106 }
107 }
108}
109
110#[derive(Debug, Clone, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct ContextOptions {
115 pub version: u32,
116 #[serde(default)]
117 pub browser_name: String,
118 #[serde(default)]
119 pub playwright_version: String,
120 #[serde(default)]
121 pub platform: String,
122 #[serde(default)]
123 pub sdk_language: String,
124 #[serde(default)]
125 pub test_id_attribute_name: String,
126 #[serde(default)]
127 pub wall_time: f64,
128 #[serde(default)]
129 pub monotonic_time: f64,
130 #[serde(default)]
131 pub context_id: String,
132 #[serde(default)]
135 pub options: Value,
136}
137
138#[derive(Debug, Clone, Deserialize)]
141#[serde(rename_all = "camelCase")]
142pub struct BeforeEvent {
143 pub call_id: String,
144 pub start_time: f64,
145 #[serde(default)]
146 pub class: String,
147 #[serde(default)]
148 pub method: String,
149 #[serde(default)]
150 pub params: Value,
151 #[serde(default)]
152 pub title: Option<String>,
153 pub page_id: Option<String>,
154 pub before_snapshot: Option<String>,
155 pub step_id: Option<String>,
156 pub parent_id: Option<String>,
157}
158
159#[derive(Debug, Clone, Deserialize)]
162#[serde(rename_all = "camelCase")]
163pub struct InputEvent {
164 pub call_id: String,
165 pub point: Option<Point>,
166 pub input_snapshot: Option<String>,
167}
168
169#[derive(Debug, Clone, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub struct LogEvent {
173 pub call_id: String,
174 pub message: String,
175 pub time: f64,
176}
177
178#[derive(Debug, Clone, Deserialize)]
180#[serde(rename_all = "camelCase")]
181pub struct AfterEvent {
182 pub call_id: String,
183 pub end_time: f64,
184 #[serde(default)]
185 pub result: Option<Value>,
186 #[serde(default)]
187 pub error: Option<ActionError>,
188 pub after_snapshot: Option<String>,
189 pub point: Option<Point>,
190}
191
192#[derive(Debug, Clone, Deserialize)]
194#[serde(rename_all = "camelCase")]
195pub struct ConsoleEvent {
196 #[serde(rename = "type", default)]
200 pub level: String,
201 #[serde(default)]
202 pub text: String,
203 #[serde(default)]
204 pub args: Vec<Value>,
205 pub location: Option<ConsoleLocation>,
206 pub time: f64,
207 pub page_id: Option<String>,
208}
209
210#[derive(Debug, Clone, Deserialize)]
211#[serde(rename_all = "camelCase")]
212pub struct ConsoleLocation {
213 #[serde(default)]
214 pub url: String,
215 #[serde(default)]
216 pub line_number: u32,
217 #[serde(default)]
218 pub column_number: u32,
219}
220
221#[derive(Debug, Clone, Deserialize)]
224#[serde(rename_all = "camelCase")]
225pub struct SystemEvent {
226 #[serde(default)]
227 pub class: String,
228 #[serde(default)]
229 pub method: String,
230 #[serde(default)]
231 pub params: Value,
232 pub time: f64,
233 pub page_id: Option<String>,
234}
235
236#[derive(Debug, Clone, Deserialize)]
241#[serde(rename_all = "camelCase")]
242pub struct FrameSnapshotEvent {
243 pub call_id: String,
244 pub snapshot_name: String,
245 pub page_id: String,
246 pub frame_id: String,
247 #[serde(default)]
248 pub frame_url: String,
249 #[serde(default)]
250 pub doctype: String,
251 #[serde(default)]
252 pub html: String,
253 pub viewport: Option<Viewport>,
254 pub timestamp: f64,
255 #[serde(default)]
256 pub wall_time: f64,
257 #[serde(default)]
258 pub collection_time: f64,
259 #[serde(default)]
260 pub is_main_frame: bool,
261 #[serde(default)]
262 pub resource_overrides: Vec<ResourceOverride>,
263}
264
265#[derive(Debug, Clone, Copy, Deserialize)]
266pub struct Viewport {
267 pub width: u32,
268 pub height: u32,
269}
270
271#[derive(Debug, Clone, Deserialize)]
275#[serde(rename_all = "camelCase")]
276pub struct ResourceOverride {
277 pub url: String,
278 #[serde(default)]
279 pub sha1: Option<String>,
280 #[serde(rename = "ref", default)]
281 pub reference: Option<String>,
282}
283
284#[derive(Debug, Clone, Deserialize)]
286#[serde(rename_all = "camelCase")]
287pub struct ScreencastFrameEvent {
288 pub page_id: String,
289 pub sha1: String,
290 pub width: u32,
291 pub height: u32,
292 pub timestamp: f64,
293}
294
295#[derive(Debug, Clone, Deserialize)]
297#[serde(rename_all = "camelCase")]
298pub struct ActionError {
299 #[serde(default)]
300 pub name: String,
301 #[serde(default)]
302 pub message: String,
303}
304
305#[derive(Debug, Clone, Copy, Deserialize)]
308pub struct Point {
309 pub x: f64,
310 pub y: f64,
311}