browser-commander 0.18.0

Universal browser automation library that supports multiple browser engines with a unified API
Documentation
//! The in-page code and viewer shared with JavaScript (issue #108).
//!
//! `assets.json` is generated by `scripts/generate-trace-assets.mjs` from
//! `js/src/traces`, so the snapshot capture, the mutation recorder and the
//! viewer that Rust ships are the same bytes JavaScript runs. It is parsed once.

use std::sync::OnceLock;

use serde::Deserialize;

const ASSETS_JSON: &str = include_str!("assets.json");

/// The in-page functions a recorder evaluates.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CaptureAssets {
    /// `function captureSnapshotInPage(options)`.
    pub capture_snapshot: String,
    /// `function installMutationRecorderInPage(options)`.
    pub install_mutation_recorder: String,
    /// `function drainMutationsInPage(globalName)`.
    pub drain_mutations: String,
    /// `function stopMutationRecorderInPage(globalName)`.
    pub stop_mutation_recorder: String,
}

/// The viewer's stylesheet and script.
#[derive(Debug, Clone, Deserialize)]
pub struct ViewerAssets {
    /// The contents of the viewer's `<style>` element.
    pub style: String,
    /// The contents of the viewer's last `<script>` element.
    pub script: String,
}

/// Everything in `assets.json`.
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TraceAssets {
    /// Says where the file comes from.
    pub note: String,
    /// The page global the mutation recorder lives under.
    pub recorder_global: String,
    /// The marker redacted values are replaced with.
    pub redacted: String,
    /// In-page functions.
    pub capture: CaptureAssets,
    /// Viewer stylesheet and script.
    pub viewer: ViewerAssets,
}

/// The shared assets, parsed on first use.
pub fn trace_assets() -> &'static TraceAssets {
    static ASSETS: OnceLock<TraceAssets> = OnceLock::new();
    ASSETS.get_or_init(|| {
        serde_json::from_str(ASSETS_JSON).expect("rust/src/traces/assets.json is generated JSON")
    })
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn assets_hold_the_in_page_functions() {
        let assets = trace_assets();
        assert_eq!(assets.recorder_global, "__browserCommanderTrace__");
        assert_eq!(assets.redacted, super::super::redaction::REDACTED);
        assert!(assets
            .capture
            .capture_snapshot
            .starts_with("function captureSnapshotInPage(options)"));
        assert!(assets
            .capture
            .drain_mutations
            .starts_with("function drainMutationsInPage(globalName)"));
        assert!(!assets.viewer.script.is_empty());
    }
}