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