leptos_browser_test/
error.rs1use std::{path::PathBuf, time::Duration};
2
3use thiserror::Error;
4
5use crate::CargoLeptosMode;
6
7#[derive(Debug, PartialEq, Eq)]
13pub struct StartupFailureContext {
14 pub app_name: String,
16 pub expected_line: String,
18 pub stdout_tail: String,
20 pub stderr_tail: String,
22}
23
24#[derive(Debug, PartialEq, Eq, Error)]
26pub enum LeptosBrowserTestError {
27 #[error("failed to resolve {app_name} directory {app_dir:?}")]
29 ResolveAppDir {
30 app_name: String,
32 app_dir: PathBuf,
34 },
35
36 #[error("failed to spawn `cargo leptos {mode_arg}` for {app_name}", mode_arg = mode.as_arg())]
38 SpawnCargoLeptos {
39 app_name: String,
41 mode: CargoLeptosMode,
43 },
44
45 #[error("failed to find a free site port for {app_name}")]
47 FindFreeSitePort {
48 app_name: String,
50 },
51
52 #[error("failed to find a free reload port for {app_name}")]
54 FindFreeReloadPort {
55 app_name: String,
57 },
58
59 #[error(
61 "{app_name} stdout closed before startup completed. Expected stdout to contain {expected_line:?}.\n\nRecent stdout:\n{stdout_tail}\n\nRecent stderr:\n{stderr_tail}",
62 app_name = .0.app_name,
63 expected_line = .0.expected_line,
64 stdout_tail = .0.stdout_tail,
65 stderr_tail = .0.stderr_tail,
66 )]
67 StartupStdoutClosed(StartupFailureContext),
68
69 #[error(
71 "{app_name} did not start within {timeout:?} ({reason}); expected stdout to contain {expected_line:?}.\n\nRecent stdout:\n{stdout_tail}\n\nRecent stderr:\n{stderr_tail}",
72 app_name = ctx.app_name,
73 expected_line = ctx.expected_line,
74 stdout_tail = ctx.stdout_tail,
75 stderr_tail = ctx.stderr_tail,
76 )]
77 StartupTimedOut {
78 ctx: StartupFailureContext,
80 timeout: Duration,
82 reason: String,
85 },
86
87 #[error(
89 "{app_name} failed to read stdout while waiting for {expected_line:?}.\n\nRecent stdout:\n{stdout_tail}\n\nRecent stderr:\n{stderr_tail}",
90 app_name = .0.app_name,
91 expected_line = .0.expected_line,
92 stdout_tail = .0.stdout_tail,
93 stderr_tail = .0.stderr_tail,
94 )]
95 StreamRead(StartupFailureContext),
96
97 #[error("invalid site_addr {site_addr:?} for {app_name}: expected `host:port`")]
99 InvalidSiteAddr {
100 app_name: String,
102 site_addr: String,
104 },
105}
106
107#[cfg(test)]
108mod tests {
109 use std::time::Duration;
110
111 use assertr::prelude::*;
112
113 use super::{LeptosBrowserTestError, StartupFailureContext};
114
115 fn ctx() -> StartupFailureContext {
116 StartupFailureContext {
117 app_name: "demo".to_owned(),
118 expected_line: "listening on".to_owned(),
119 stdout_tail: "out-line".to_owned(),
120 stderr_tail: "err-line".to_owned(),
121 }
122 }
123
124 #[test]
125 fn startup_stdout_closed_display_matches_documented_format() {
126 let err = LeptosBrowserTestError::StartupStdoutClosed(ctx());
127 assert_that!(err.to_string()).is_equal_to(
128 "demo stdout closed before startup completed. Expected stdout to contain \"listening on\".\n\nRecent stdout:\nout-line\n\nRecent stderr:\nerr-line"
129 .to_owned(),
130 );
131 }
132
133 #[test]
134 fn startup_timed_out_display_matches_documented_format() {
135 let err = LeptosBrowserTestError::StartupTimedOut {
136 ctx: ctx(),
137 timeout: Duration::from_secs(7),
138 reason: "tight bound for unit-style smoke test".to_owned(),
139 };
140 assert_that!(err.to_string()).is_equal_to(
141 "demo did not start within 7s (tight bound for unit-style smoke test); expected stdout to contain \"listening on\".\n\nRecent stdout:\nout-line\n\nRecent stderr:\nerr-line"
142 .to_owned(),
143 );
144 }
145
146 #[test]
147 fn stream_read_display_matches_documented_format() {
148 let err = LeptosBrowserTestError::StreamRead(ctx());
149 assert_that!(err.to_string()).is_equal_to(
150 "demo failed to read stdout while waiting for \"listening on\".\n\nRecent stdout:\nout-line\n\nRecent stderr:\nerr-line"
151 .to_owned(),
152 );
153 }
154}