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:
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