viewpoint_test/expect/
page.rs1use std::time::Duration;
4
5use viewpoint_core::Page;
6
7use crate::error::AssertionError;
8
9const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
11
12pub struct PageAssertions<'a> {
14 page: &'a Page,
15 timeout: Duration,
16 is_negated: bool,
17}
18
19impl<'a> PageAssertions<'a> {
20 pub fn new(page: &'a Page) -> Self {
22 Self {
23 page,
24 timeout: DEFAULT_TIMEOUT,
25 is_negated: false,
26 }
27 }
28
29 #[must_use]
31 pub fn timeout(mut self, timeout: Duration) -> Self {
32 self.timeout = timeout;
33 self
34 }
35
36 #[must_use]
40 pub fn negated(mut self) -> Self {
41 self.is_negated = !self.is_negated;
42 self
43 }
44
45 #[must_use]
50 #[allow(clippy::should_implement_trait)]
51 pub fn not(self) -> Self {
52 self.negated()
53 }
54
55 pub async fn to_have_url(&self, expected: &str) -> Result<(), AssertionError> {
61 let start = std::time::Instant::now();
62
63 loop {
64 let url =
65 self.page.url().await.map_err(|e| {
66 AssertionError::new("Failed to get URL", expected, e.to_string())
67 })?;
68
69 let matches = url == expected;
70 let expected_match = !self.is_negated;
71
72 if matches == expected_match {
73 return Ok(());
74 }
75
76 if start.elapsed() >= self.timeout {
77 return Err(AssertionError::new(
78 if self.is_negated {
79 "Page should not have URL"
80 } else {
81 "Page should have URL"
82 },
83 if self.is_negated {
84 format!("not \"{expected}\"")
85 } else {
86 expected.to_string()
87 },
88 url,
89 ));
90 }
91
92 tokio::time::sleep(Duration::from_millis(100)).await;
93 }
94 }
95
96 pub async fn to_have_url_containing(&self, expected: &str) -> Result<(), AssertionError> {
102 let start = std::time::Instant::now();
103
104 loop {
105 let url =
106 self.page.url().await.map_err(|e| {
107 AssertionError::new("Failed to get URL", expected, e.to_string())
108 })?;
109
110 let contains = url.contains(expected);
111 let expected_match = !self.is_negated;
112
113 if contains == expected_match {
114 return Ok(());
115 }
116
117 if start.elapsed() >= self.timeout {
118 return Err(AssertionError::new(
119 if self.is_negated {
120 "Page URL should not contain"
121 } else {
122 "Page URL should contain"
123 },
124 if self.is_negated {
125 format!("not containing \"{expected}\"")
126 } else {
127 format!("containing \"{expected}\"")
128 },
129 url,
130 ));
131 }
132
133 tokio::time::sleep(Duration::from_millis(100)).await;
134 }
135 }
136
137 pub async fn to_have_title(&self, expected: &str) -> Result<(), AssertionError> {
143 let start = std::time::Instant::now();
144
145 loop {
146 let title =
147 self.page.title().await.map_err(|e| {
148 AssertionError::new("Failed to get title", expected, e.to_string())
149 })?;
150
151 let matches = title == expected;
152 let expected_match = !self.is_negated;
153
154 if matches == expected_match {
155 return Ok(());
156 }
157
158 if start.elapsed() >= self.timeout {
159 return Err(AssertionError::new(
160 if self.is_negated {
161 "Page should not have title"
162 } else {
163 "Page should have title"
164 },
165 if self.is_negated {
166 format!("not \"{expected}\"")
167 } else {
168 expected.to_string()
169 },
170 title,
171 ));
172 }
173
174 tokio::time::sleep(Duration::from_millis(100)).await;
175 }
176 }
177
178 pub async fn to_have_title_containing(&self, expected: &str) -> Result<(), AssertionError> {
184 let start = std::time::Instant::now();
185
186 loop {
187 let title =
188 self.page.title().await.map_err(|e| {
189 AssertionError::new("Failed to get title", expected, e.to_string())
190 })?;
191
192 let contains = title.contains(expected);
193 let expected_match = !self.is_negated;
194
195 if contains == expected_match {
196 return Ok(());
197 }
198
199 if start.elapsed() >= self.timeout {
200 return Err(AssertionError::new(
201 if self.is_negated {
202 "Page title should not contain"
203 } else {
204 "Page title should contain"
205 },
206 if self.is_negated {
207 format!("not containing \"{expected}\"")
208 } else {
209 format!("containing \"{expected}\"")
210 },
211 title,
212 ));
213 }
214
215 tokio::time::sleep(Duration::from_millis(100)).await;
216 }
217 }
218}