Skip to main content

chrome_for_testing/api/
channel.rs

1use serde::{Deserialize, Serialize};
2use std::fmt::{Debug, Display};
3use std::str::FromStr;
4
5/// Error returned when parsing a channel string fails.
6#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
7#[error(
8    "Unknown channel: '{value}'. Expected one of: Stable, Beta, Dev, Canary (or lowercased alternative)"
9)]
10pub struct ParseChannelError {
11    value: String,
12}
13
14/// Chrome release channel.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Channel {
17    /// The stable release channel - the default Chrome version for general users.
18    Stable,
19
20    /// The beta release channel - preview of upcoming stable features.
21    /// Less stable than stable, used for testing new functionality before it reaches stable.
22    Beta,
23
24    /// The dev release channel - early development builds with cutting-edge features.
25    /// Less stable than beta, intended for developers and early adopters.
26    Dev,
27
28    /// The canary release channel - nightly builds with the absolute latest changes.
29    /// Less stable than dev, highly experimental.
30    Canary,
31}
32
33impl Display for Channel {
34    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35        // Use the Debug implementation.
36        write!(f, "{self:?}")
37    }
38}
39
40impl FromStr for Channel {
41    type Err = ParseChannelError;
42
43    fn from_str(s: &str) -> Result<Self, Self::Err> {
44        match s {
45            "Stable" | "stable" => Ok(Channel::Stable),
46            "Beta" | "beta" => Ok(Channel::Beta),
47            "Dev" | "dev" => Ok(Channel::Dev),
48            "Canary" | "canary" => Ok(Channel::Canary),
49            _ => Err(ParseChannelError {
50                value: s.to_owned(),
51            }),
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use assertr::prelude::*;
60
61    #[test]
62    fn parse_to_string_round_trip() {
63        fn capitalize_first(s: &str) -> String {
64            s.chars()
65                .take(1)
66                .flat_map(|f| f.to_uppercase())
67                .chain(s.chars().skip(1))
68                .collect()
69        }
70
71        let channels = [
72            ("Stable", Channel::Stable),
73            ("stable", Channel::Stable),
74            ("Beta", Channel::Beta),
75            ("beta", Channel::Beta),
76            ("Dev", Channel::Dev),
77            ("dev", Channel::Dev),
78            ("Canary", Channel::Canary),
79            ("canary", Channel::Canary),
80        ];
81        for (test, expected) in channels {
82            assert_that!(test.parse::<Channel>())
83                .is_ok()
84                .is_equal_to(expected);
85            assert_that!(expected.to_string()).is_equal_to(capitalize_first(test));
86        }
87    }
88
89    #[test]
90    fn parse_unknown_variants_failed() {
91        assert_that!("unknown".parse::<Channel>())
92            .is_err()
93            .is_equal_to(ParseChannelError {
94                value: "unknown".to_string(),
95            });
96    }
97
98    #[test]
99    fn serialized_value_matches_display_output() {
100        assert_that!(serde_json::to_string(&Channel::Stable).unwrap())
101            .is_equal_to(String::from("\"Stable\""));
102    }
103}