Skip to main content

playwright_rs/protocol/
coverage.rs

1// Coverage — Chromium-only code coverage collection
2//
3// See: https://playwright.dev/docs/api/class-coverage
4
5use crate::error::Result;
6use crate::protocol::page::Page;
7
8/// Options for `Coverage::start_js_coverage`.
9///
10/// See: <https://playwright.dev/docs/api/class-coverage#coverage-start-js-coverage>
11#[derive(Debug, Default, Clone)]
12pub struct StartJSCoverageOptions {
13    /// Whether to reset coverage on every navigation.
14    ///
15    /// Defaults to `true`.
16    pub reset_on_navigation: Option<bool>,
17
18    /// Whether to report anonymous scripts generated by the page.
19    ///
20    /// Defaults to `false`.
21    pub report_anonymous_scripts: Option<bool>,
22}
23
24/// Options for `Coverage::start_css_coverage`.
25///
26/// See: <https://playwright.dev/docs/api/class-coverage#coverage-start-css-coverage>
27#[derive(Debug, Default, Clone)]
28pub struct StartCSSCoverageOptions {
29    /// Whether to reset coverage on every navigation.
30    ///
31    /// Defaults to `true`.
32    pub reset_on_navigation: Option<bool>,
33}
34
35/// A byte-offset range within a CSS stylesheet.
36///
37/// Used in [`CSSCoverageEntry`].
38#[derive(Debug, Clone, serde::Deserialize)]
39pub struct CoverageRange {
40    /// Start byte offset (inclusive).
41    pub start: usize,
42    /// End byte offset (exclusive).
43    pub end: usize,
44}
45
46/// A byte-offset range with hit count within a JavaScript function.
47///
48/// Used in [`JSFunctionCoverage`].
49#[derive(Debug, Clone, serde::Deserialize)]
50pub struct JSCoverageRange {
51    /// Start byte offset (inclusive).
52    #[serde(rename = "startOffset")]
53    pub start_offset: usize,
54    /// End byte offset (exclusive).
55    #[serde(rename = "endOffset")]
56    pub end_offset: usize,
57    /// Number of times this range was executed.
58    pub count: i64,
59}
60
61/// Per-function coverage data within a [`JSCoverageEntry`].
62#[derive(Debug, Clone, serde::Deserialize)]
63pub struct JSFunctionCoverage {
64    /// The function name (empty string for anonymous functions).
65    #[serde(rename = "functionName")]
66    pub function_name: String,
67    /// Whether this is block-level coverage (true) or function-level (false).
68    #[serde(rename = "isBlockCoverage")]
69    pub is_block_coverage: bool,
70    /// Covered byte-offset ranges within this function.
71    pub ranges: Vec<JSCoverageRange>,
72}
73
74/// A JavaScript coverage entry returned by `Coverage::stop_js_coverage`.
75///
76/// See: <https://playwright.dev/docs/api/class-coverage#coverage-stop-js-coverage>
77#[derive(Debug, Clone, serde::Deserialize)]
78pub struct JSCoverageEntry {
79    /// The URL of the script.
80    pub url: String,
81    /// The V8 script ID.
82    #[serde(rename = "scriptId")]
83    pub script_id: String,
84    /// The script source text.
85    pub source: Option<String>,
86    /// Per-function coverage data.
87    pub functions: Vec<JSFunctionCoverage>,
88}
89
90/// A CSS coverage entry returned by `Coverage::stop_css_coverage`.
91///
92/// See: <https://playwright.dev/docs/api/class-coverage#coverage-stop-css-coverage>
93#[derive(Debug, Clone, serde::Deserialize)]
94pub struct CSSCoverageEntry {
95    /// The URL of the stylesheet.
96    pub url: String,
97    /// The stylesheet source text.
98    pub text: Option<String>,
99    /// Byte-offset ranges of used CSS rules.
100    pub ranges: Vec<CoverageRange>,
101}
102
103/// Provides JavaScript and CSS code coverage collection (Chromium only).
104///
105/// Access via [`Page::coverage`].
106///
107/// Coverage collection is only supported in Chromium. Calling these methods on
108/// Firefox or WebKit will return an error.
109///
110/// See: <https://playwright.dev/docs/api/class-coverage>
111#[derive(Clone)]
112pub struct Coverage {
113    page: Page,
114}
115
116impl Coverage {
117    pub(crate) fn new(page: Page) -> Self {
118        Self { page }
119    }
120
121    /// Starts collecting JavaScript coverage.
122    ///
123    /// Must be called before navigating to the page(s) you want to measure.
124    ///
125    /// # Errors
126    ///
127    /// Returns error if coverage is already started, if the browser is not
128    /// Chromium, or if the RPC call fails.
129    ///
130    /// See: <https://playwright.dev/docs/api/class-coverage#coverage-start-js-coverage>
131    pub async fn start_js_coverage(&self, options: Option<StartJSCoverageOptions>) -> Result<()> {
132        self.page.coverage_start_js(options).await
133    }
134
135    /// Stops JavaScript coverage collection and returns the entries.
136    ///
137    /// # Errors
138    ///
139    /// Returns error if coverage was not started or if the RPC call fails.
140    ///
141    /// See: <https://playwright.dev/docs/api/class-coverage#coverage-stop-js-coverage>
142    pub async fn stop_js_coverage(&self) -> Result<Vec<JSCoverageEntry>> {
143        self.page.coverage_stop_js().await
144    }
145
146    /// Starts collecting CSS coverage.
147    ///
148    /// # Errors
149    ///
150    /// Returns error if coverage is already started, if the browser is not
151    /// Chromium, or if the RPC call fails.
152    ///
153    /// See: <https://playwright.dev/docs/api/class-coverage#coverage-start-css-coverage>
154    pub async fn start_css_coverage(&self, options: Option<StartCSSCoverageOptions>) -> Result<()> {
155        self.page.coverage_start_css(options).await
156    }
157
158    /// Stops CSS coverage collection and returns the entries.
159    ///
160    /// # Errors
161    ///
162    /// Returns error if coverage was not started or if the RPC call fails.
163    ///
164    /// See: <https://playwright.dev/docs/api/class-coverage#coverage-stop-css-coverage>
165    pub async fn stop_css_coverage(&self) -> Result<Vec<CSSCoverageEntry>> {
166        self.page.coverage_stop_css().await
167    }
168}