Skip to main content

chrome_for_testing_manager/
version.rs

1use chrome_for_testing::{
2    Channel, Download, Platform, Version, VersionInChannel, VersionWithoutChannel,
3};
4
5/// How to pick which Chrome / `ChromeDriver` version to install and run.
6///
7/// See the named constructors ([`Self::stable`], [`Self::beta`], [`Self::dev`], [`Self::canary`])
8/// and the `From<Channel>` / `From<Version>` impls for the most ergonomic forms.
9#[derive(Debug, Clone, PartialEq, Eq)]
10#[non_exhaustive]
11pub enum VersionRequest {
12    /// Uses the latest working version. Might not be stable yet.
13    /// You may want to prefer variant [`VersionRequest::LatestIn`] instead.
14    Latest,
15
16    /// Use the latest release from the given [`Channel`],
17    /// e.g. the one from the [`Channel::Stable`] channel.
18    LatestIn(Channel),
19
20    /// Pin a specific version to use.
21    Fixed(Version),
22}
23
24impl From<Channel> for VersionRequest {
25    fn from(channel: Channel) -> Self {
26        Self::LatestIn(channel)
27    }
28}
29
30impl From<Version> for VersionRequest {
31    fn from(version: Version) -> Self {
32        Self::Fixed(version)
33    }
34}
35
36impl VersionRequest {
37    /// Latest release from the [`Channel::Stable`] channel.
38    #[must_use]
39    pub fn stable() -> Self {
40        Self::LatestIn(Channel::Stable)
41    }
42
43    /// Latest release from the [`Channel::Beta`] channel.
44    #[must_use]
45    pub fn beta() -> Self {
46        Self::LatestIn(Channel::Beta)
47    }
48
49    /// Latest release from the [`Channel::Dev`] channel.
50    #[must_use]
51    pub fn dev() -> Self {
52        Self::LatestIn(Channel::Dev)
53    }
54
55    /// Latest release from the [`Channel::Canary`] channel.
56    #[must_use]
57    pub fn canary() -> Self {
58        Self::LatestIn(Channel::Canary)
59    }
60}
61
62/// A version of Chrome and `ChromeDriver` that has been resolved against the
63/// chrome-for-testing release index but not yet downloaded.
64///
65/// Construct via [`crate::ChromeForTestingManager::resolve_version`] and pass into
66/// [`crate::ChromeForTestingManager::download`] with one or more [`crate::ChromeBinary`] values.
67#[derive(Debug)]
68pub struct SelectedVersion {
69    pub(crate) channel: Option<Channel>,
70    pub(crate) version: Version,
71    pub(crate) chrome: Option<Download>,
72    pub(crate) chrome_headless_shell: Option<Download>,
73    pub(crate) chromedriver: Option<Download>,
74}
75
76impl SelectedVersion {
77    /// The release channel this version was resolved through, if any.
78    /// `None` for versions resolved by [`VersionRequest::Latest`] or [`VersionRequest::Fixed`].
79    #[must_use]
80    pub fn channel(&self) -> Option<&Channel> {
81        self.channel.as_ref()
82    }
83
84    /// The pinned [`Version`] that will be downloaded.
85    #[must_use]
86    pub fn version(&self) -> Version {
87        self.version
88    }
89
90    /// Whether a Chrome download exists for this version on the detected platform.
91    #[must_use]
92    pub fn has_chrome_download(&self) -> bool {
93        self.chrome.is_some()
94    }
95
96    /// Whether a Chrome Headless Shell download exists for this version on the detected platform.
97    #[must_use]
98    pub fn has_chrome_headless_shell_download(&self) -> bool {
99        self.chrome_headless_shell.is_some()
100    }
101
102    /// Whether a `ChromeDriver` download exists for this version on the detected platform.
103    #[must_use]
104    pub fn has_chromedriver_download(&self) -> bool {
105        self.chromedriver.is_some()
106    }
107}
108
109impl From<(VersionWithoutChannel, Platform)> for SelectedVersion {
110    fn from((v, p): (VersionWithoutChannel, Platform)) -> Self {
111        SelectedVersion {
112            channel: None,
113            version: v.version,
114            chrome: v.downloads.chrome_for_platform(p).cloned(),
115            chrome_headless_shell: v.downloads.chrome_headless_shell_for_platform(p).cloned(),
116            chromedriver: v.downloads.chromedriver_for_platform(p).cloned(),
117        }
118    }
119}
120
121impl From<(VersionInChannel, Platform)> for SelectedVersion {
122    fn from((v, p): (VersionInChannel, Platform)) -> Self {
123        let chrome_download = v.downloads.chrome_for_platform(p).cloned();
124        let chromedriver_download = v.downloads.chromedriver_for_platform(p).cloned();
125
126        SelectedVersion {
127            channel: Some(v.channel),
128            version: v.version,
129            chrome: chrome_download,
130            chrome_headless_shell: v.downloads.chrome_headless_shell_for_platform(p).cloned(),
131            chromedriver: chromedriver_download,
132        }
133    }
134}
135
136#[cfg(test)]
137mod tests {
138    use super::*;
139    use assertr::prelude::*;
140
141    mod version_request {
142        use super::*;
143
144        #[test]
145        fn from_channel_resolves_to_latest_in_channel() {
146            assert_that!(VersionRequest::from(Channel::Stable))
147                .is_equal_to(VersionRequest::LatestIn(Channel::Stable));
148        }
149
150        #[test]
151        fn named_constructors_match_explicit_variants() {
152            assert_that!(VersionRequest::stable())
153                .is_equal_to(VersionRequest::LatestIn(Channel::Stable));
154            assert_that!(VersionRequest::beta())
155                .is_equal_to(VersionRequest::LatestIn(Channel::Beta));
156            assert_that!(VersionRequest::dev()).is_equal_to(VersionRequest::LatestIn(Channel::Dev));
157            assert_that!(VersionRequest::canary())
158                .is_equal_to(VersionRequest::LatestIn(Channel::Canary));
159        }
160
161        #[test]
162        fn from_parsed_version_resolves_to_fixed() {
163            let v: Version = "135.0.7019.0".parse().expect("valid version literal");
164            assert_that!(VersionRequest::from(v)).is_equal_to(VersionRequest::Fixed(v));
165        }
166    }
167}