upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2023-10-01 00:00:00 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2023-10-01 00:00:00 +0100
commite237328ec611a5891586530c1d3cb26c16c1093b (patch)
tree22ac36baa240354d06ae82eb070609fa3e3fcb82 /tests
parent000901c0cbca8464b5a89bcc93c5474f6564bafd (diff)
feat(login) fetch user relays and metadata
get user relay list and metadata events from relays when keys are used and last fetch attempt was more than an hour ago uses user's write relays if known, otherwise uses fallback relays to achieve this a method for intergration testing event fetching from relays was added
Diffstat (limited to 'tests')
-rw-r--r--tests/login.rs1100
-rw-r--r--tests/prs_create.rs22
2 files changed, 855 insertions, 267 deletions
diff --git a/tests/login.rs b/tests/login.rs
index a75608d..d565620 100644
--- a/tests/login.rs
+++ b/tests/login.rs
@@ -8,7 +8,7 @@ static EXPECTED_SET_PASSWORD_CONFIRM_PROMPT: &str = "confirm password";
8static EXPECTED_PASSWORD_PROMPT: &str = "password"; 8static EXPECTED_PASSWORD_PROMPT: &str = "password";
9 9
10fn standard_login() -> Result<CliTester> { 10fn standard_login() -> Result<CliTester> {
11 let mut p = CliTester::new(["login"]); 11 let mut p = CliTester::new(["login", "--offline"]);
12 12
13 p.expect_input_eventually(EXPECTED_NSEC_PROMPT)? 13 p.expect_input_eventually(EXPECTED_NSEC_PROMPT)?
14 .succeeds_with(TEST_KEY_1_NSEC)?; 14 .succeeds_with(TEST_KEY_1_NSEC)?;
@@ -20,74 +20,602 @@ fn standard_login() -> Result<CliTester> {
20 p.expect_end_eventually()?; 20 p.expect_end_eventually()?;
21 Ok(p) 21 Ok(p)
22} 22}
23mod with_relays {
24 use anyhow::Ok;
25 use futures::join;
26 use test_utils::relay::{shutdown_relay, ListenerReqFunc, Relay};
23 27
24mod when_first_time_login {
25 use super::*; 28 use super::*;
26 29
27 #[test] 30 mod when_first_time_login {
28 #[serial] 31 use super::*;
29 fn prompts_for_nsec_and_password() -> Result<()> {
30 before()?;
31 standard_login()?;
32 after()
33 }
34
35 #[test]
36 #[serial]
37 fn succeeds_with_text_logged_in_as_npub() -> Result<()> {
38 with_fresh_config(|| {
39 let mut p = CliTester::new(["login"]);
40 32
41 p.expect_input(EXPECTED_NSEC_PROMPT)? 33 // falls_back_to_fallback_relays - this is implict in the tests
42 .succeeds_with(TEST_KEY_1_NSEC)?; 34
35 mod dislays_logged_in_with_correct_name {
36
37 use super::*;
38
39 async fn run_test_displays_correct_name(
40 relay_listener1: Option<ListenerReqFunc<'_>>,
41 relay_listener2: Option<ListenerReqFunc<'_>>,
42 ) -> Result<()> {
43 let (mut r51, mut r52) = (
44 Relay::new(8051, None, relay_listener1),
45 Relay::new(8052, None, relay_listener2),
46 );
47
48 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
49 with_fresh_config(|| {
50 let mut p = CliTester::new(["login"]);
51
52 p.expect_input(EXPECTED_NSEC_PROMPT)?
53 .succeeds_with(TEST_KEY_1_NSEC)?;
54
55 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
56 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
57 .succeeds_with(TEST_PASSWORD)?;
58
59 p.expect("searching for your details...\r\n")?;
60 p.expect("\r")?;
61
62 p.expect_end_with("logged in as fred\r\n")?;
63 for p in [51, 52] {
64 shutdown_relay(8000 + p)?;
65 }
66 Ok(())
67 })
68 });
69
70 // launch relay
71 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
72
73 cli_tester_handle.join().unwrap()?;
74 Ok(())
75 }
76
77 #[test]
78 #[serial]
79 fn when_latest_metadata_and_relay_list_on_all_relays() -> Result<()> {
80 futures::executor::block_on(run_test_displays_correct_name(
81 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
82 relay.respond_events(
83 client_id,
84 &subscription_id,
85 &vec![
86 generate_test_key_1_metadata_event("fred"),
87 generate_test_key_1_relay_list_event(),
88 ],
89 )?;
90 Ok(())
91 }),
92 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
93 relay.respond_events(
94 client_id,
95 &subscription_id,
96 &vec![
97 generate_test_key_1_metadata_event("fred"),
98 generate_test_key_1_relay_list_event(),
99 ],
100 )?;
101 Ok(())
102 }),
103 ))
104 }
105
106 #[test]
107 #[serial]
108 fn when_latest_metadata_and_relay_list_on_some_relays_but_others_have_none()
109 -> Result<()> {
110 futures::executor::block_on(run_test_displays_correct_name(
111 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
112 relay.respond_events(
113 client_id,
114 &subscription_id,
115 &vec![
116 generate_test_key_1_metadata_event("fred"),
117 generate_test_key_1_relay_list_event(),
118 ],
119 )?;
120 Ok(())
121 }),
122 None,
123 ))
124 }
125
126 #[test]
127 #[serial]
128 fn when_latest_metadata_only_on_relay_and_relay_list_on_another() -> Result<()> {
129 futures::executor::block_on(run_test_displays_correct_name(
130 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
131 relay.respond_events(
132 client_id,
133 &subscription_id,
134 &vec![generate_test_key_1_metadata_event("fred")],
135 )?;
136 Ok(())
137 }),
138 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
139 relay.respond_events(
140 client_id,
141 &subscription_id,
142 &vec![generate_test_key_1_relay_list_event()],
143 )?;
144 Ok(())
145 }),
146 ))
147 }
148
149 #[test]
150 #[serial]
151 fn when_some_relays_return_old_metadata_event() -> Result<()> {
152 futures::executor::block_on(run_test_displays_correct_name(
153 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
154 relay.respond_events(
155 client_id,
156 &subscription_id,
157 &vec![
158 generate_test_key_1_metadata_event("fred"),
159 generate_test_key_1_relay_list_event(),
160 ],
161 )?;
162 Ok(())
163 }),
164 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
165 relay.respond_events(
166 client_id,
167 &subscription_id,
168 &vec![generate_test_key_1_metadata_event_old("fred old")],
169 )?;
170 Ok(())
171 }),
172 ))
173 }
174
175 #[test]
176 #[serial]
177 fn when_some_relays_return_other_users_metadata() -> Result<()> {
178 futures::executor::block_on(run_test_displays_correct_name(
179 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
180 relay.respond_events(
181 client_id,
182 &subscription_id,
183 &vec![generate_test_key_2_metadata_event("carole")],
184 )?;
185 Ok(())
186 }),
187 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
188 relay.respond_events(
189 client_id,
190 &subscription_id,
191 &vec![
192 generate_test_key_1_metadata_event_old("fred"),
193 generate_test_key_1_relay_list_event(),
194 ],
195 )?;
196 Ok(())
197 }),
198 ))
199 }
200
201 #[test]
202 #[serial]
203 fn when_some_relays_return_other_event_kinds() -> Result<()> {
204 futures::executor::block_on(run_test_displays_correct_name(
205 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
206 let mut event = generate_test_key_1_metadata_event("Fred");
207 event.kind = nostr::Kind::TextNote;
208 relay.respond_events(
209 client_id,
210 &subscription_id,
211 &vec![make_event_old_or_change_user(event, &TEST_KEY_1_KEYS, 0)],
212 )?;
213 Ok(())
214 }),
215 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
216 relay.respond_events(
217 client_id,
218 &subscription_id,
219 &vec![
220 generate_test_key_1_metadata_event_old("fred"),
221 generate_test_key_1_relay_list_event(),
222 ],
223 )?;
224 Ok(())
225 }),
226 ))
227 }
228
229 mod when_specifying_command_line_nsec_only {
230 use super::*;
231
232 #[test]
233 #[serial]
234 fn displays_correct_name() -> Result<()> {
235 futures::executor::block_on(
236 run_test_when_specifying_command_line_nsec_only_displays_correct_name(
237 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
238 relay.respond_events(
239 client_id,
240 &subscription_id,
241 &vec![
242 generate_test_key_1_metadata_event("fred"),
243 generate_test_key_1_relay_list_event(),
244 ],
245 )?;
246 Ok(())
247 }),
248 None,
249 ),
250 )
251 }
252 async fn run_test_when_specifying_command_line_nsec_only_displays_correct_name(
253 relay_listener1: Option<ListenerReqFunc<'_>>,
254 relay_listener2: Option<ListenerReqFunc<'_>>,
255 ) -> Result<()> {
256 let (mut r51, mut r52) = (
257 Relay::new(8051, None, relay_listener1),
258 Relay::new(8052, None, relay_listener2),
259 );
260
261 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
262 with_fresh_config(|| {
263 let mut p = CliTester::new(["login", "--nsec", TEST_KEY_1_NSEC]);
264
265 p.expect("searching for your details...\r\n")?;
266 p.expect("\r")?;
267
268 p.expect_end_with("logged in as fred\r\n")?;
269 for p in [51, 52] {
270 shutdown_relay(8000 + p)?;
271 }
272 Ok(())
273 })
274 });
275
276 // launch relay
277 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
278
279 cli_tester_handle.join().unwrap()?;
280 Ok(())
281 }
282 }
283 mod when_specifying_command_line_password_only {
284 use super::*;
285
286 #[test]
287 #[serial]
288 fn displays_correct_name() -> Result<()> {
289 futures::executor::block_on(
290 run_test_when_specifying_command_line_password_only_displays_correct_name(
291 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
292 relay.respond_events(
293 client_id,
294 &subscription_id,
295 &vec![
296 generate_test_key_1_metadata_event("fred"),
297 generate_test_key_1_relay_list_event(),
298 ],
299 )?;
300 Ok(())
301 }),
302 None,
303 ),
304 )
305 }
306 async fn run_test_when_specifying_command_line_password_only_displays_correct_name(
307 relay_listener1: Option<ListenerReqFunc<'_>>,
308 relay_listener2: Option<ListenerReqFunc<'_>>,
309 ) -> Result<()> {
310 let (mut r51, mut r52) = (
311 Relay::new(8051, None, relay_listener1),
312 Relay::new(8052, None, relay_listener2),
313 );
314
315 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
316 with_fresh_config(|| {
317 CliTester::new([
318 "login",
319 "--offline",
320 "--nsec",
321 TEST_KEY_1_NSEC,
322 "--password",
323 TEST_PASSWORD,
324 ])
325 .expect_end_eventually()?;
326
327 let mut p = CliTester::new(["login", "--password", TEST_PASSWORD]);
328
329 p.expect("searching for your details...\r\n")?;
330 p.expect("\r")?;
331
332 p.expect_end_with("logged in as fred\r\n")?;
333 for p in [51, 52] {
334 shutdown_relay(8000 + p)?;
335 }
336 Ok(())
337 })
338 });
339
340 // launch relay
341 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
342
343 cli_tester_handle.join().unwrap()?;
344 Ok(())
345 }
346 }
347
348 mod when_specifying_command_line_nsec_and_password {
349 use super::*;
350
351 #[test]
352 #[serial]
353 fn displays_correct_name() -> Result<()> {
354 futures::executor::block_on(
355 run_test_when_specifying_command_line_nsec_and_password_displays_correct_name(
356 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
357 relay.respond_events(
358 client_id,
359 &subscription_id,
360 &vec![
361 generate_test_key_1_metadata_event("fred"),
362 generate_test_key_1_relay_list_event(),
363 ],
364 )?;
365 Ok(())
366 }),
367 None,
368 ),
369 )
370 }
371 async fn run_test_when_specifying_command_line_nsec_and_password_displays_correct_name(
372 relay_listener1: Option<ListenerReqFunc<'_>>,
373 relay_listener2: Option<ListenerReqFunc<'_>>,
374 ) -> Result<()> {
375 let (mut r51, mut r52) = (
376 Relay::new(8051, None, relay_listener1),
377 Relay::new(8052, None, relay_listener2),
378 );
379
380 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
381 with_fresh_config(|| {
382 let mut p = CliTester::new([
383 "login",
384 "--nsec",
385 TEST_KEY_1_NSEC,
386 "--password",
387 TEST_PASSWORD,
388 ]);
389
390 p.expect("searching for your details...\r\n")?;
391 p.expect("\r")?;
392
393 p.expect_end_with("logged in as fred\r\n")?;
394 for p in [51, 52] {
395 shutdown_relay(8000 + p)?;
396 }
397 Ok(())
398 })
399 });
400
401 // launch relay
402 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
403
404 cli_tester_handle.join().unwrap()?;
405 Ok(())
406 }
407 }
408 }
43 409
44 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)? 410 mod when_no_metadata_found {
45 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)? 411 use super::*;
46 .succeeds_with(TEST_PASSWORD)?; 412
413 #[test]
414 #[serial]
415 fn warm_user_and_displays_npub() -> Result<()> {
416 futures::executor::block_on(
417 run_test_when_no_metadata_found_warns_user_and_uses_npub(None, None),
418 )
419 }
420
421 async fn run_test_when_no_metadata_found_warns_user_and_uses_npub(
422 relay_listener1: Option<ListenerReqFunc<'_>>,
423 relay_listener2: Option<ListenerReqFunc<'_>>,
424 ) -> Result<()> {
425 let (mut r51, mut r52) = (
426 Relay::new(8051, None, relay_listener1),
427 Relay::new(8052, None, relay_listener2),
428 );
429
430 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
431 with_fresh_config(|| {
432 let mut p = CliTester::new(["login"]);
433
434 p.expect_input(EXPECTED_NSEC_PROMPT)?
435 .succeeds_with(TEST_KEY_1_NSEC)?;
436
437 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
438 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
439 .succeeds_with(TEST_PASSWORD)?;
440
441 p.expect("searching for your details...\r\n")?;
442 p.expect("\r")?;
443 p.expect("cannot find your account metadata (name, etc) on relays\r\n")?;
444
445 p.expect_end_with(format!("logged in as {TEST_KEY_1_NPUB}\r\n").as_str())?;
446 for p in [51, 52] {
447 shutdown_relay(8000 + p)?;
448 }
449 Ok(())
450 })
451 });
452
453 // launch relay
454 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
455
456 cli_tester_handle.join().unwrap()?;
457 Ok(())
458 }
459 }
47 460
48 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 461 mod when_metadata_but_no_relay_list_found {
49 }) 462 use super::*;
463
464 #[test]
465 #[serial]
466 fn warm_user_and_displays_name() -> Result<()> {
467 futures::executor::block_on(
468 run_test_when_no_relay_list_found_warns_user_and_uses_npub(
469 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
470 relay.respond_events(
471 client_id,
472 &subscription_id,
473 &vec![generate_test_key_1_metadata_event("fred")],
474 )?;
475 Ok(())
476 }),
477 None,
478 ),
479 )
480 }
481
482 async fn run_test_when_no_relay_list_found_warns_user_and_uses_npub(
483 relay_listener1: Option<ListenerReqFunc<'_>>,
484 relay_listener2: Option<ListenerReqFunc<'_>>,
485 ) -> Result<()> {
486 let (mut r51, mut r52) = (
487 Relay::new(8051, None, relay_listener1),
488 Relay::new(8052, None, relay_listener2),
489 );
490
491 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
492 with_fresh_config(|| {
493 let mut p = CliTester::new(["login"]);
494
495 p.expect_input(EXPECTED_NSEC_PROMPT)?
496 .succeeds_with(TEST_KEY_1_NSEC)?;
497
498 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
499 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
500 .succeeds_with(TEST_PASSWORD)?;
501
502 p.expect("searching for your details...\r\n")?;
503 p.expect("\r")?;
504 p.expect("cannot find your relay list. consider using another nostr client to create one to enhance your nostr experience.\r\n")?;
505
506 p.expect_end_with("logged in as fred\r\n")?;
507 for p in [51, 52] {
508 shutdown_relay(8000 + p)?;
509 }
510 Ok(())
511 })
512 });
513
514 // launch relay
515 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
516
517 cli_tester_handle.join().unwrap()?;
518 Ok(())
519 }
520 }
50 } 521 }
51 522
52 #[test] 523 mod when_second_time_login_and_details_already_fetched {
53 #[serial] 524 use super::*;
54 fn succeeds_with_hex_secret_key_in_place_of_nsec() -> Result<()> {
55 with_fresh_config(|| {
56 let mut p = CliTester::new(["login"]);
57
58 p.expect_input(EXPECTED_NSEC_PROMPT)?
59 .succeeds_with(TEST_KEY_1_SK_HEX)?;
60
61 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
62 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
63 .succeeds_with(TEST_PASSWORD)?;
64 525
65 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 526 // TODO: the following two tests would require a fake config file or
66 }) 527 // fake time
528 // - uses_relays_from_user_relay_list
529 // - dislays_correct_name - when_local_metadata_is_the_most_recent
530
531 mod uses_cache {
532 use super::*;
533
534 #[test]
535 #[serial]
536 fn dislays_logged_in_with_correct_name() -> Result<()> {
537 futures::executor::block_on(run_test_dislays_logged_in_with_correct_name(Some(
538 &|relay, client_id, subscription_id, _| -> Result<()> {
539 relay.respond_events(
540 client_id,
541 &subscription_id,
542 &vec![
543 generate_test_key_1_metadata_event("fred"),
544 generate_test_key_1_relay_list_event(),
545 ],
546 )?;
547 Ok(())
548 },
549 )))
550 }
551 async fn run_test_dislays_logged_in_with_correct_name(
552 relay_listener: Option<ListenerReqFunc<'_>>,
553 ) -> Result<()> {
554 let (mut r51, mut r52) = (
555 Relay::new(8051, None, relay_listener),
556 Relay::new(8052, None, None),
557 );
558
559 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
560 with_fresh_config(|| {
561 let mut p = CliTester::new([
562 "login",
563 "--nsec",
564 TEST_KEY_1_NSEC,
565 "--password",
566 TEST_PASSWORD,
567 ]);
568
569 p.expect_end_eventually_with("logged in as fred\r\n")?;
570
571 for p in [51, 52] {
572 shutdown_relay(8000 + p)?;
573 }
574
575 let mut p = CliTester::new(["login", "--password", TEST_PASSWORD]);
576
577 p.expect("searching for your details...\r\n")?;
578 p.expect("\r")?;
579
580 p.expect_end_eventually_with("logged in as fred\r\n")?;
581
582 Ok(())
583 })
584 });
585
586 // launch relay
587 let _ = join!(r51.listen_until_close(), r52.listen_until_close(),);
588
589 cli_tester_handle.join().unwrap()?;
590
591 Ok(())
592 }
593 }
67 } 594 }
595}
68 596
69 mod when_invalid_nsec { 597/// using the offline flag simplifies the test. relay interaction is tested
598/// seperately
599mod with_offline_flag {
600 use super::*;
601 mod when_first_time_login {
70 use super::*; 602 use super::*;
71 603
72 #[test] 604 #[test]
73 #[serial] 605 #[serial]
74 fn prompts_for_nsec_until_valid() -> Result<()> { 606 fn prompts_for_nsec_and_password() -> Result<()> {
75 with_fresh_config(|| { 607 before()?;
76 let invalid_nsec_response = 608 standard_login()?;
77 "invalid nsec. try again with nsec (or hex private key)"; 609 after()
610 }
78 611
79 let mut p = CliTester::new(["login"]); 612 #[test]
613 #[serial]
614 fn succeeds_with_text_logged_in_as_npub() -> Result<()> {
615 with_fresh_config(|| {
616 let mut p = CliTester::new(["login", "--offline"]);
80 617
81 p.expect_input(EXPECTED_NSEC_PROMPT)? 618 p.expect_input(EXPECTED_NSEC_PROMPT)?
82 // this behaviour is intentional. rejecting the response with dialoguer hides
83 // the original input from the user so they cannot see the
84 // mistake they made.
85 .succeeds_with(TEST_INVALID_NSEC)?;
86
87 p.expect_input(invalid_nsec_response)?
88 .succeeds_with(TEST_INVALID_NSEC)?;
89
90 p.expect_input(invalid_nsec_response)?
91 .succeeds_with(TEST_KEY_1_NSEC)?; 619 .succeeds_with(TEST_KEY_1_NSEC)?;
92 620
93 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)? 621 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
@@ -97,178 +625,174 @@ mod when_first_time_login {
97 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 625 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
98 }) 626 })
99 } 627 }
100 }
101}
102 628
103mod when_second_time_login { 629 #[test]
104 use super::*; 630 #[serial]
631 fn succeeds_with_hex_secret_key_in_place_of_nsec() -> Result<()> {
632 with_fresh_config(|| {
633 let mut p = CliTester::new(["login", "--offline"]);
105 634
106 #[test] 635 p.expect_input(EXPECTED_NSEC_PROMPT)?
107 #[serial] 636 .succeeds_with(TEST_KEY_1_SK_HEX)?;
108 fn prints_login_as_npub() -> Result<()> {
109 with_fresh_config(|| {
110 standard_login()?.exit()?;
111 637
112 CliTester::new(["login"]) 638 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
113 .expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())? 639 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
114 .exit() 640 .succeeds_with(TEST_PASSWORD)?;
115 })
116 }
117 641
118 #[test] 642 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
119 #[serial] 643 })
120 fn prompts_for_password_and_succeeds_with_logged_in_as_npub() -> Result<()> { 644 }
121 with_fresh_config(|| {
122 standard_login()?.exit()?;
123 645
124 let mut p = CliTester::new(["login"]); 646 mod when_invalid_nsec {
647 use super::*;
125 648
126 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())? 649 #[test]
127 .expect_password(EXPECTED_PASSWORD_PROMPT)? 650 #[serial]
128 .succeeds_with(TEST_PASSWORD)?; 651 fn prompts_for_nsec_until_valid() -> Result<()> {
652 with_fresh_config(|| {
653 let invalid_nsec_response =
654 "invalid nsec. try again with nsec (or hex private key)";
129 655
130 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 656 let mut p = CliTester::new(["login", "--offline"]);
131 })
132 }
133 657
134 #[test] 658 p.expect_input(EXPECTED_NSEC_PROMPT)?
135 #[serial] 659 // this behaviour is intentional. rejecting the response with dialoguer
136 fn when_invalid_password_exit_with_error() -> Result<()> { 660 // hides the original input from the user so they
137 with_fresh_config(|| { 661 // cannot see the mistake they made.
138 standard_login()?.exit()?; 662 .succeeds_with(TEST_INVALID_NSEC)?;
139 663
140 let mut p = CliTester::new(["login"]); 664 p.expect_input(invalid_nsec_response)?
665 .succeeds_with(TEST_INVALID_NSEC)?;
141 666
142 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())? 667 p.expect_input(invalid_nsec_response)?
143 .expect_password(EXPECTED_PASSWORD_PROMPT)? 668 .succeeds_with(TEST_KEY_1_NSEC)?;
144 .succeeds_with(TEST_INVALID_PASSWORD)?;
145 p.expect_end_with(format!("Error: failed to log in as {}\r\n\r\nCaused by:\r\n 0: failed to decrypt key with provided password\r\n 1: failed to decrypt\r\n", TEST_KEY_1_NPUB).as_str())
146 })
147 }
148}
149 669
150mod when_called_with_nsec_parameter_only { 670 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
151 use super::*; 671 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
672 .succeeds_with(TEST_PASSWORD)?;
152 673
153 #[test] 674 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
154 #[serial] 675 })
155 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> { 676 }
156 with_fresh_config(|| { 677 }
157 CliTester::new(["login", "--nsec", TEST_KEY_1_NSEC])
158 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
159 })
160 } 678 }
161 679
162 #[test] 680 mod when_second_time_login {
163 #[serial] 681 use super::*;
164 fn forgets_identity() -> Result<()> {
165 with_fresh_config(|| {
166 CliTester::new(["login", "--nsec", TEST_KEY_1_NSEC])
167 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
168 682
169 let mut p = CliTester::new(["login"]); 683 #[test]
684 #[serial]
685 fn prints_login_as_npub() -> Result<()> {
686 with_fresh_config(|| {
687 standard_login()?.exit()?;
170 688
171 p.expect_input(EXPECTED_NSEC_PROMPT)? 689 CliTester::new(["login", "--offline"])
172 .succeeds_with(TEST_KEY_1_NSEC)?; 690 .expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
691 .exit()
692 })
693 }
173 694
174 p.exit() 695 #[test]
175 }) 696 #[serial]
176 } 697 fn prompts_for_password_and_succeeds_with_logged_in_as_npub() -> Result<()> {
698 with_fresh_config(|| {
699 standard_login()?.exit()?;
177 700
178 mod when_logging_in_as_different_nsec { 701 let mut p = CliTester::new(["login", "--offline"]);
179 use super::*; 702
703 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
704 .expect_password(EXPECTED_PASSWORD_PROMPT)?
705 .succeeds_with(TEST_PASSWORD)?;
706
707 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
708 })
709 }
180 710
181 #[test] 711 #[test]
182 #[serial] 712 #[serial]
183 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> { 713 fn when_invalid_password_exit_with_error() -> Result<()> {
184 with_fresh_config(|| { 714 with_fresh_config(|| {
185 standard_login()?.exit()?; 715 standard_login()?.exit()?;
186 716
187 CliTester::new(["login", "--nsec", TEST_KEY_2_NSEC]) 717 let mut p = CliTester::new(["login", "--offline"]);
188 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str()) 718
719 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
720 .expect_password(EXPECTED_PASSWORD_PROMPT)?
721 .succeeds_with(TEST_INVALID_PASSWORD)?;
722 p.expect_end_with(format!("Error: failed to log in as {}\r\n\r\nCaused by:\r\n 0: failed to decrypt key with provided password\r\n 1: failed to decrypt\r\n", TEST_KEY_1_NPUB).as_str())
189 }) 723 })
190 } 724 }
191 } 725 }
192 #[test]
193 #[serial]
194 fn invalid_nsec_param_fails_without_prompts() -> Result<()> {
195 with_fresh_config(|| {
196 CliTester::new(["login", "--nsec", TEST_INVALID_NSEC]).expect_end_with(
197 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n",
198 )
199 })
200 }
201}
202 726
203mod when_called_with_nsec_and_password_parameter { 727 mod when_called_with_nsec_parameter_only {
204 use super::*; 728 use super::*;
205 729
206 #[test] 730 #[test]
207 #[serial] 731 #[serial]
208 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> { 732 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> {
209 with_fresh_config(|| { 733 with_fresh_config(|| {
210 CliTester::new([ 734 CliTester::new(["login", "--offline", "--nsec", TEST_KEY_1_NSEC])
211 "login", 735 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
212 "--nsec", 736 })
213 TEST_KEY_1_NSEC, 737 }
214 "--password",
215 TEST_PASSWORD,
216 ])
217 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
218 })
219 }
220 738
221 #[test] 739 #[test]
222 #[serial] 740 #[serial]
223 fn remembers_identity() -> Result<()> { 741 fn forgets_identity() -> Result<()> {
224 with_fresh_config(|| { 742 with_fresh_config(|| {
225 CliTester::new([ 743 CliTester::new(["login", "--offline", "--nsec", TEST_KEY_1_NSEC])
226 "login", 744 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
227 "--nsec", 745
228 TEST_KEY_1_NSEC, 746 let mut p = CliTester::new(["login", "--offline"]);
229 "--password",
230 TEST_PASSWORD,
231 ])
232 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
233
234 CliTester::new(["login"])
235 .expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
236 .exit()
237 })
238 }
239 747
240 #[test] 748 p.expect_input(EXPECTED_NSEC_PROMPT)?
241 #[serial] 749 .succeeds_with(TEST_KEY_1_NSEC)?;
242 fn parameters_can_be_called_globally() -> Result<()> { 750
243 with_fresh_config(|| { 751 p.exit()
244 CliTester::new([ 752 })
245 "--nsec", 753 }
246 TEST_KEY_1_NSEC, 754
247 "--password", 755 mod when_logging_in_as_different_nsec {
248 TEST_PASSWORD, 756 use super::*;
249 "login", 757
250 ]) 758 #[test]
251 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 759 #[serial]
252 }) 760 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> {
761 with_fresh_config(|| {
762 standard_login()?.exit()?;
763
764 CliTester::new(["login", "--offline", "--nsec", TEST_KEY_2_NSEC])
765 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str())
766 })
767 }
768 }
769 #[test]
770 #[serial]
771 fn invalid_nsec_param_fails_without_prompts() -> Result<()> {
772 with_fresh_config(|| {
773 CliTester::new(["login", "--offline", "--nsec", TEST_INVALID_NSEC]).expect_end_with(
774 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n",
775 )
776 })
777 }
253 } 778 }
254 779
255 mod when_logging_in_as_different_nsec { 780 mod when_called_with_nsec_and_password_parameter {
256 use super::*; 781 use super::*;
257 782
258 #[test] 783 #[test]
259 #[serial] 784 #[serial]
260 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> { 785 fn valid_nsec_param_succeeds_without_prompts() -> Result<()> {
261 with_fresh_config(|| { 786 with_fresh_config(|| {
262 standard_login()?.exit()?;
263
264 CliTester::new([ 787 CliTester::new([
265 "login", 788 "login",
789 "--offline",
266 "--nsec", 790 "--nsec",
267 TEST_KEY_2_NSEC, 791 TEST_KEY_1_NSEC,
268 "--password", 792 "--password",
269 TEST_PASSWORD, 793 TEST_PASSWORD,
270 ]) 794 ])
271 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str()) 795 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
272 }) 796 })
273 } 797 }
274 798
@@ -276,120 +800,182 @@ mod when_called_with_nsec_and_password_parameter {
276 #[serial] 800 #[serial]
277 fn remembers_identity() -> Result<()> { 801 fn remembers_identity() -> Result<()> {
278 with_fresh_config(|| { 802 with_fresh_config(|| {
279 standard_login()?.exit()?;
280
281 CliTester::new([ 803 CliTester::new([
282 "login", 804 "login",
805 "--offline",
283 "--nsec", 806 "--nsec",
284 TEST_KEY_2_NSEC, 807 TEST_KEY_1_NSEC,
285 "--password", 808 "--password",
286 TEST_PASSWORD, 809 TEST_PASSWORD,
287 ]) 810 ])
288 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str())?; 811 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
289 812
290 CliTester::new(["login"]) 813 CliTester::new(["login", "--offline"])
291 .expect(format!("login as {}\r\n", TEST_KEY_2_NPUB).as_str())? 814 .expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
292 .exit() 815 .exit()
293 }) 816 })
294 } 817 }
295 }
296
297 mod when_provided_with_new_password {
298 use super::*;
299 818
300 #[test] 819 #[test]
301 #[serial] 820 #[serial]
302 fn password_changes() -> Result<()> { 821 fn parameters_can_be_called_globally() -> Result<()> {
303 with_fresh_config(|| { 822 with_fresh_config(|| {
304 standard_login()?.exit()?;
305
306 CliTester::new([ 823 CliTester::new([
307 "login",
308 "--nsec", 824 "--nsec",
309 TEST_KEY_1_NSEC, 825 TEST_KEY_1_NSEC,
310 "--password", 826 "--password",
311 TEST_INVALID_PASSWORD, 827 TEST_PASSWORD,
828 "login",
829 "--offline",
312 ]) 830 ])
313 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?; 831 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
314
315 CliTester::new(["--password", TEST_INVALID_PASSWORD, "login"])
316 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
317 }) 832 })
318 } 833 }
319 }
320 834
321 #[test] 835 mod when_logging_in_as_different_nsec {
322 #[serial] 836 use super::*;
323 fn invalid_nsec_param_fails_without_prompts() -> Result<()> { 837
324 with_fresh_config(|| { 838 #[test]
325 CliTester::new([ 839 #[serial]
326 "login", 840 fn valid_nsec_param_succeeds_without_prompts_and_logs_in() -> Result<()> {
327 "--nsec", 841 with_fresh_config(|| {
328 TEST_INVALID_NSEC, 842 standard_login()?.exit()?;
329 "--password", 843
330 TEST_PASSWORD, 844 CliTester::new([
331 ]) 845 "login",
332 .expect_end_with( 846 "--offline",
333 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n", 847 "--nsec",
334 ) 848 TEST_KEY_2_NSEC,
335 }) 849 "--password",
850 TEST_PASSWORD,
851 ])
852 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str())
853 })
854 }
855
856 #[test]
857 #[serial]
858 fn remembers_identity() -> Result<()> {
859 with_fresh_config(|| {
860 standard_login()?.exit()?;
861
862 CliTester::new([
863 "login",
864 "--offline",
865 "--nsec",
866 TEST_KEY_2_NSEC,
867 "--password",
868 TEST_PASSWORD,
869 ])
870 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_2_NPUB).as_str())?;
871
872 CliTester::new(["login", "--offline"])
873 .expect(format!("login as {}\r\n", TEST_KEY_2_NPUB).as_str())?
874 .exit()
875 })
876 }
877 }
878
879 mod when_provided_with_new_password {
880 use super::*;
881
882 #[test]
883 #[serial]
884 fn password_changes() -> Result<()> {
885 with_fresh_config(|| {
886 standard_login()?.exit()?;
887
888 CliTester::new([
889 "login",
890 "--offline",
891 "--nsec",
892 TEST_KEY_1_NSEC,
893 "--password",
894 TEST_INVALID_PASSWORD,
895 ])
896 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
897
898 CliTester::new(["--password", TEST_INVALID_PASSWORD, "login", "--offline"])
899 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
900 })
901 }
902 }
903
904 #[test]
905 #[serial]
906 fn invalid_nsec_param_fails_without_prompts() -> Result<()> {
907 with_fresh_config(|| {
908 CliTester::new([
909 "login",
910 "--offline",
911 "--nsec",
912 TEST_INVALID_NSEC,
913 "--password",
914 TEST_PASSWORD,
915 ])
916 .expect_end_with(
917 "Error: invalid nsec parameter\r\n\r\nCaused by:\r\n Invalid secret key\r\n",
918 )
919 })
920 }
336 } 921 }
337}
338 922
339mod when_called_with_password_parameter_only { 923 mod when_called_with_password_parameter_only {
340 use super::*; 924 use super::*;
341 925
342 #[test] 926 #[test]
343 #[serial] 927 #[serial]
344 fn when_nsec_stored_logs_in_without_prompts() -> Result<()> { 928 fn when_nsec_stored_logs_in_without_prompts() -> Result<()> {
345 with_fresh_config(|| { 929 with_fresh_config(|| {
346 standard_login()?.exit()?; 930 standard_login()?.exit()?;
347 931
348 CliTester::new(["login", "--password", TEST_PASSWORD]) 932 CliTester::new(["login", "--offline", "--password", TEST_PASSWORD])
349 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 933 .expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
350 }) 934 })
351 } 935 }
352 936
353 #[test] 937 #[test]
354 #[serial] 938 #[serial]
355 fn when_no_nsec_stored_logs_error() -> Result<()> { 939 fn when_no_nsec_stored_logs_error() -> Result<()> {
356 with_fresh_config(|| { 940 with_fresh_config(|| {
357 CliTester::new(["login", "--password", TEST_PASSWORD]) 941 CliTester::new(["login", "--offline", "--password", TEST_PASSWORD]).expect_end_with(
358 .expect_end_with("Error: no nsec available to decrypt with specified password\r\n") 942 "Error: no nsec available to decrypt with specified password\r\n",
359 }) 943 )
944 })
945 }
360 } 946 }
361}
362 947
363mod when_weak_password { 948 mod when_weak_password {
364 use super::*; 949 use super::*;
365 950
366 #[test] 951 #[test]
367 #[serial] 952 #[serial]
368 // combined into a single test as it is computationally expensive to run 953 // combined into a single test as it is computationally expensive to run
369 fn warns_it_might_take_a_few_seconds_then_succeeds_then_second_login_prompts_for_password_then_warns_again_then_succeeds() 954 fn warns_it_might_take_a_few_seconds_then_succeeds_then_second_login_prompts_for_password_then_warns_again_then_succeeds()
370 -> Result<()> { 955 -> Result<()> {
371 with_fresh_config(|| { 956 with_fresh_config(|| {
372 let mut p = CliTester::new_with_timeout(10000, ["login"]); 957 let mut p = CliTester::new_with_timeout(10000, ["login", "--offline"]);
373 p.expect_input(EXPECTED_NSEC_PROMPT)? 958 p.expect_input(EXPECTED_NSEC_PROMPT)?
374 .succeeds_with(TEST_KEY_1_NSEC)?; 959 .succeeds_with(TEST_KEY_1_NSEC)?;
375 960
376 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)? 961 p.expect_password(EXPECTED_SET_PASSWORD_PROMPT)?
377 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)? 962 .with_confirmation(EXPECTED_SET_PASSWORD_CONFIRM_PROMPT)?
378 .succeeds_with(TEST_WEAK_PASSWORD)?; 963 .succeeds_with(TEST_WEAK_PASSWORD)?;
379 964
380 p.expect("this may take a few seconds...\r\n")?; 965 p.expect("this may take a few seconds...\r\n")?;
381 966
382 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?; 967 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())?;
383 968
384 p = CliTester::new_with_timeout(10000, ["login"]); 969 p = CliTester::new_with_timeout(10000, ["login", "--offline"]);
385 970
386 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())? 971 p.expect(format!("login as {}\r\n", TEST_KEY_1_NPUB).as_str())?
387 .expect_password(EXPECTED_PASSWORD_PROMPT)? 972 .expect_password(EXPECTED_PASSWORD_PROMPT)?
388 .succeeds_with(TEST_WEAK_PASSWORD)?; 973 .succeeds_with(TEST_WEAK_PASSWORD)?;
389 974
390 p.expect("this may take a few seconds...\r\n")?; 975 p.expect("this may take a few seconds...\r\n")?;
391 976
392 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str()) 977 p.expect_end_with(format!("logged in as {}\r\n", TEST_KEY_1_NPUB).as_str())
393 }) 978 })
979 }
394 } 980 }
395} 981}
diff --git a/tests/prs_create.rs b/tests/prs_create.rs
index 0863496..564ef16 100644
--- a/tests/prs_create.rs
+++ b/tests/prs_create.rs
@@ -195,9 +195,9 @@ mod sends_pr_and_2_patches_to_3_relays {
195 let git_repo = prep_git_repo()?; 195 let git_repo = prep_git_repo()?;
196 196
197 let (mut r51, mut r52, mut r53) = ( 197 let (mut r51, mut r52, mut r53) = (
198 Relay::new(8051, None), 198 Relay::new(8051, None, None),
199 Relay::new(8052, None), 199 Relay::new(8052, None, None),
200 Relay::new(8053, None), 200 Relay::new(8053, None, None),
201 ); 201 );
202 202
203 // // check relay had the right number of events 203 // // check relay had the right number of events
@@ -427,9 +427,9 @@ mod sends_pr_and_2_patches_to_3_relays {
427 let git_repo = prep_git_repo()?; 427 let git_repo = prep_git_repo()?;
428 428
429 let (mut r51, mut r52, mut r53) = ( 429 let (mut r51, mut r52, mut r53) = (
430 Relay::new(8051, None), 430 Relay::new(8051, None, None),
431 Relay::new(8052, None), 431 Relay::new(8052, None, None),
432 Relay::new(8053, None), 432 Relay::new(8053, None, None),
433 ); 433 );
434 434
435 // // check relay had the right number of events 435 // // check relay had the right number of events
@@ -477,15 +477,16 @@ mod sends_pr_and_2_patches_to_3_relays {
477 let git_repo = prep_git_repo()?; 477 let git_repo = prep_git_repo()?;
478 478
479 let (mut r51, mut r52, mut r53) = ( 479 let (mut r51, mut r52, mut r53) = (
480 Relay::new(8051, None), 480 Relay::new(8051, None, None),
481 Relay::new( 481 Relay::new(
482 8052, 482 8052,
483 Some(&|relay, client_id, event| -> Result<()> { 483 Some(&|relay, client_id, event| -> Result<()> {
484 relay.respond_ok(client_id, event, Some("Payment Required"))?; 484 relay.respond_ok(client_id, event, Some("Payment Required"))?;
485 Ok(()) 485 Ok(())
486 }), 486 }),
487 None,
487 ), 488 ),
488 Relay::new(8053, None), 489 Relay::new(8053, None, None),
489 ); 490 );
490 491
491 // // check relay had the right number of events 492 // // check relay had the right number of events
@@ -523,15 +524,16 @@ mod sends_pr_and_2_patches_to_3_relays {
523 let git_repo = prep_git_repo()?; 524 let git_repo = prep_git_repo()?;
524 525
525 let (mut r51, mut r52, mut r53) = ( 526 let (mut r51, mut r52, mut r53) = (
526 Relay::new(8051, None), 527 Relay::new(8051, None, None),
527 Relay::new( 528 Relay::new(
528 8052, 529 8052,
529 Some(&|relay, client_id, event| -> Result<()> { 530 Some(&|relay, client_id, event| -> Result<()> {
530 relay.respond_ok(client_id, event, Some("Payment Required"))?; 531 relay.respond_ok(client_id, event, Some("Payment Required"))?;
531 Ok(()) 532 Ok(())
532 }), 533 }),
534 None,
533 ), 535 ),
534 Relay::new(8053, None), 536 Relay::new(8053, None, None),
535 ); 537 );
536 538
537 // // check relay had the right number of events 539 // // check relay had the right number of events