use serde::Deserialize;
use serde_json::{Map, Value};
#[derive(Debug, Clone)]
pub struct RawEvent {
raw: Map<String, Value>,
}
impl RawEvent {
pub(crate) fn new(raw: Map<String, Value>) -> Self {
Self { raw }
}
pub fn kind(&self) -> Option<&str> {
self.raw.get("type").and_then(|v| v.as_str())
}
pub fn as_value(&self) -> &Map<String, Value> {
&self.raw
}
pub fn into_value(self) -> Value {
Value::Object(self.raw)
}
pub fn into_typed(self) -> TraceEvent {
match serde_json::from_value::<TypedEnum>(Value::Object(self.raw.clone())) {
Ok(t) => t.into(),
Err(_) => TraceEvent::Unknown(self),
}
}
}
#[derive(Debug, Clone)]
pub enum TraceEvent {
ContextOptions(ContextOptions),
Before(BeforeEvent),
Input(InputEvent),
Log(LogEvent),
After(AfterEvent),
Console(ConsoleEvent),
Event(SystemEvent),
FrameSnapshot(FrameSnapshotEvent),
ScreencastFrame(ScreencastFrameEvent),
Unknown(RawEvent),
}
#[derive(Deserialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
enum TypedEnum {
ContextOptions(ContextOptions),
Before(BeforeEvent),
Input(InputEvent),
Log(LogEvent),
After(AfterEvent),
Console(ConsoleEvent),
Event(SystemEvent),
FrameSnapshot(FrameSnapshotEvent),
ScreencastFrame(ScreencastFrameEvent),
}
impl From<TypedEnum> for TraceEvent {
fn from(t: TypedEnum) -> Self {
match t {
TypedEnum::ContextOptions(c) => TraceEvent::ContextOptions(c),
TypedEnum::Before(b) => TraceEvent::Before(b),
TypedEnum::Input(i) => TraceEvent::Input(i),
TypedEnum::Log(l) => TraceEvent::Log(l),
TypedEnum::After(a) => TraceEvent::After(a),
TypedEnum::Console(c) => TraceEvent::Console(c),
TypedEnum::Event(e) => TraceEvent::Event(e),
TypedEnum::FrameSnapshot(f) => TraceEvent::FrameSnapshot(f),
TypedEnum::ScreencastFrame(s) => TraceEvent::ScreencastFrame(s),
}
}
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ContextOptions {
pub version: u32,
#[serde(default)]
pub browser_name: String,
#[serde(default)]
pub playwright_version: String,
#[serde(default)]
pub platform: String,
#[serde(default)]
pub sdk_language: String,
#[serde(default)]
pub test_id_attribute_name: String,
#[serde(default)]
pub wall_time: f64,
#[serde(default)]
pub monotonic_time: f64,
#[serde(default)]
pub context_id: String,
#[serde(default)]
pub options: Value,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BeforeEvent {
pub call_id: String,
pub start_time: f64,
#[serde(default)]
pub class: String,
#[serde(default)]
pub method: String,
#[serde(default)]
pub params: Value,
#[serde(default)]
pub title: Option<String>,
pub page_id: Option<String>,
pub before_snapshot: Option<String>,
pub step_id: Option<String>,
pub parent_id: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct InputEvent {
pub call_id: String,
pub point: Option<Point>,
pub input_snapshot: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LogEvent {
pub call_id: String,
pub message: String,
pub time: f64,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AfterEvent {
pub call_id: String,
pub end_time: f64,
#[serde(default)]
pub result: Option<Value>,
#[serde(default)]
pub error: Option<ActionError>,
pub after_snapshot: Option<String>,
pub point: Option<Point>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConsoleEvent {
#[serde(rename = "type", default)]
pub level: String,
#[serde(default)]
pub text: String,
#[serde(default)]
pub args: Vec<Value>,
pub location: Option<ConsoleLocation>,
pub time: f64,
pub page_id: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConsoleLocation {
#[serde(default)]
pub url: String,
#[serde(default)]
pub line_number: u32,
#[serde(default)]
pub column_number: u32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SystemEvent {
#[serde(default)]
pub class: String,
#[serde(default)]
pub method: String,
#[serde(default)]
pub params: Value,
pub time: f64,
pub page_id: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct FrameSnapshotEvent {
pub call_id: String,
pub snapshot_name: String,
pub page_id: String,
pub frame_id: String,
#[serde(default)]
pub frame_url: String,
#[serde(default)]
pub doctype: String,
#[serde(default)]
pub html: String,
pub viewport: Option<Viewport>,
pub timestamp: f64,
#[serde(default)]
pub wall_time: f64,
#[serde(default)]
pub collection_time: f64,
#[serde(default)]
pub is_main_frame: bool,
#[serde(default)]
pub resource_overrides: Vec<ResourceOverride>,
}
#[derive(Debug, Clone, Copy, Deserialize)]
pub struct Viewport {
pub width: u32,
pub height: u32,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ResourceOverride {
pub url: String,
#[serde(default)]
pub sha1: Option<String>,
#[serde(rename = "ref", default)]
pub reference: Option<String>,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ScreencastFrameEvent {
pub page_id: String,
pub sha1: String,
pub width: u32,
pub height: u32,
pub timestamp: f64,
}
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ActionError {
#[serde(default)]
pub name: String,
#[serde(default)]
pub message: String,
}
#[derive(Debug, Clone, Copy, Deserialize)]
pub struct Point {
pub x: f64,
pub y: f64,
}