this repo has no description
1use assert_matches::assert_matches;
2use clap::Parser;
3
4use browser_stream::cli::CliArgs;
5use browser_stream::error::ConfigError;
6use browser_stream::rtmp::RtmpError;
7
8#[test]
9fn parses_defaults_and_required_fields() {
10 let args = CliArgs::try_parse_from([
11 "browser-stream",
12 "--url",
13 "https://example.com",
14 "--output",
15 "rtmp://live.example.com/app/stream",
16 ])
17 .expect("cli parse should succeed");
18
19 let config = args.into_config().expect("config should validate");
20
21 assert_eq!(config.width, 1920);
22 assert_eq!(config.height, 1080);
23 assert_eq!(config.fps, 30);
24 assert_eq!(config.bitrate_kbps, 4500);
25 assert_eq!(config.keyint_sec, 1);
26 assert_eq!(config.x264_opts, "bframes=0");
27 assert_eq!(config.retries, 5);
28 assert_eq!(config.retry_backoff_ms, 1000);
29 assert_eq!(config.startup_delay_ms, 2000);
30 assert_eq!(config.frame_timeout_ms, 30000);
31 assert!(!config.no_audio);
32}
33
34#[test]
35fn requires_destination_settings() {
36 let args = CliArgs::try_parse_from(["browser-stream", "--url", "https://example.com"])
37 .expect("cli parse should succeed");
38
39 let err = args.into_config().expect_err("validation should fail");
40 assert_matches!(err, ConfigError::Rtmp(RtmpError::MissingDestination));
41}
42
43#[test]
44fn output_precedence_wins_over_split_fields() {
45 let args = CliArgs::try_parse_from([
46 "browser-stream",
47 "--url",
48 "https://example.com",
49 "--output",
50 "rtmps://primary.example.com/app/final",
51 "--rtmp-url",
52 "rtmp://secondary.example.com/app",
53 "--stream-key",
54 "secondary",
55 ])
56 .expect("cli parse should succeed");
57
58 let config = args.into_config().expect("config should validate");
59 assert_eq!(config.output, "rtmps://primary.example.com/app/final");
60}
61
62#[test]
63fn rejects_non_http_website_scheme() {
64 let args = CliArgs::try_parse_from([
65 "browser-stream",
66 "--url",
67 "file:///tmp/index.html",
68 "--output",
69 "rtmp://live.example.com/app/key",
70 ])
71 .expect("cli parse should succeed");
72
73 let err = args.into_config().expect_err("validation should fail");
74 assert_matches!(err, ConfigError::UnsupportedWebsiteScheme(s) if s == "file");
75}
76
77#[test]
78fn rejects_out_of_range_fps() {
79 let args = CliArgs::try_parse_from([
80 "browser-stream",
81 "--url",
82 "https://example.com",
83 "--output",
84 "rtmp://live.example.com/app/key",
85 "--fps",
86 "121",
87 ])
88 .expect("cli parse should succeed");
89
90 let err = args.into_config().expect_err("validation should fail");
91 assert_matches!(
92 err,
93 ConfigError::OutOfRange { field, min: 1, max: 120, actual: 121 } if field == "fps"
94 );
95}
96
97#[test]
98fn rejects_out_of_range_frame_timeout() {
99 let args = CliArgs::try_parse_from([
100 "browser-stream",
101 "--url",
102 "https://example.com",
103 "--output",
104 "rtmp://live.example.com/app/key",
105 "--frame-timeout-ms",
106 "500",
107 ])
108 .expect("cli parse should succeed");
109
110 let err = args.into_config().expect_err("validation should fail");
111 assert_matches!(
112 err,
113 ConfigError::OutOfRange {
114 field,
115 min: 1000,
116 max,
117 actual: 500
118 } if field == "frame-timeout-ms" && max == u64::MAX
119 );
120}