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>2024-02-13 14:52:24 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2024-02-13 15:55:54 +0000
commitcf319efc6dcdc6c54564cb84e13218edbf3643fa (patch)
treeccccf807fac6c2ab242b2d6bb322c679ae5b94f7 /tests
parent3112576195aef212622d27ad9164336796c1953e (diff)
feat!: nip34 make pr event optional
use first patch as thread root if pr event isn't present. begin renaming pr event to cover letter. fix patch ordering upon creation. patches were in youngest first order which caused: - `PATCH n/t`to be in reverse order - the youngest patch was the marked root - oldest patch replied to the youngest fix finding most recent patch event. when a patch in a set is the most recent it will share a created_at with other patches. previously the first patch recieved from relay in the set would be used. now it finds the first patch with that created_at which isn't also a parent of another patch with the same created_at.
Diffstat (limited to 'tests')
-rw-r--r--tests/prs_create.rs483
-rw-r--r--tests/prs_list.rs241
2 files changed, 562 insertions, 162 deletions
diff --git a/tests/prs_create.rs b/tests/prs_create.rs
index 6272ccd..316c9fe 100644
--- a/tests/prs_create.rs
+++ b/tests/prs_create.rs
@@ -1,6 +1,7 @@
1use anyhow::Result; 1use anyhow::Result;
2use futures::join;
2use serial_test::serial; 3use serial_test::serial;
3use test_utils::{git::GitTestRepo, *}; 4use test_utils::{git::GitTestRepo, relay::Relay, *};
4 5
5#[test] 6#[test]
6fn when_to_branch_doesnt_exist_return_error() -> Result<()> { 7fn when_to_branch_doesnt_exist_return_error() -> Result<()> {
@@ -150,121 +151,133 @@ fn is_patch(event: &nostr::Event) -> bool {
150 && !event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) 151 && !event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
151} 152}
152 153
153mod sends_pr_and_2_patches_to_3_relays { 154fn prep_git_repo() -> Result<GitTestRepo> {
154 use futures::join; 155 let test_repo = GitTestRepo::default();
155 use test_utils::relay::Relay; 156 test_repo.populate()?;
156 157 // create feature branch with 2 commit ahead
157 use super::*; 158 test_repo.create_branch("feature")?;
159 test_repo.checkout("feature")?;
160 std::fs::write(test_repo.dir.join("t3.md"), "some content")?;
161 test_repo.stage_and_commit("add t3.md")?;
162 std::fs::write(test_repo.dir.join("t4.md"), "some content")?;
163 test_repo.stage_and_commit("add t4.md")?;
164 Ok(test_repo)
165}
158 166
159 fn prep_git_repo() -> Result<GitTestRepo> { 167fn cli_tester_create_pr(git_repo: &GitTestRepo, include_cover_letter: bool) -> CliTester {
160 let test_repo = GitTestRepo::default(); 168 let mut args = vec![
161 test_repo.populate()?; 169 "--nsec",
162 // create feature branch with 2 commit ahead 170 TEST_KEY_1_NSEC,
163 test_repo.create_branch("feature")?; 171 "--password",
164 test_repo.checkout("feature")?; 172 TEST_PASSWORD,
165 std::fs::write(test_repo.dir.join("t3.md"), "some content")?; 173 "--disable-cli-spinners",
166 test_repo.stage_and_commit("add t3.md")?; 174 "prs",
167 std::fs::write(test_repo.dir.join("t4.md"), "some content")?; 175 "create",
168 test_repo.stage_and_commit("add t4.md")?; 176 ];
169 Ok(test_repo) 177 if include_cover_letter {
178 for arg in [
179 "--title",
180 "exampletitle",
181 "--description",
182 "exampledescription",
183 ] {
184 args.push(arg);
185 }
186 } else {
187 args.push("--no-cover-letter");
170 } 188 }
189 CliTester::new_from_dir(&git_repo.dir, args)
190}
171 191
172 fn cli_tester_create_pr(git_repo: &GitTestRepo) -> CliTester { 192fn expect_msgs_first(p: &mut CliTester, include_cover_letter: bool) -> Result<()> {
173 CliTester::new_from_dir( 193 p.expect("creating patch for 2 commits from 'head' that can be merged into 'main'\r\n")?;
174 &git_repo.dir, 194 p.expect("searching for your details...\r\n")?;
175 [ 195 p.expect("\r")?;
176 "--nsec", 196 p.expect("logged in as fred\r\n")?;
177 TEST_KEY_1_NSEC, 197 p.expect(format!(
178 "--password", 198 "posting 2 patches {} a covering letter...\r\n",
179 TEST_PASSWORD, 199 if include_cover_letter {
180 "--disable-cli-spinners", 200 "with"
181 "prs", 201 } else {
182 "create", 202 "without"
183 "--title", 203 }
184 "exampletitle", 204 ))?;
185 "--description", 205 Ok(())
186 "exampledescription", 206}
187 ],
188 )
189 }
190 207
191 fn expect_msgs_first(p: &mut CliTester) -> Result<()> { 208async fn prep_run_create_pr(
192 p.expect("creating patch for 2 commits from 'head' that can be merged into 'main'\r\n")?; 209 include_cover_letter: bool,
193 p.expect("searching for your details...\r\n")?; 210) -> Result<(
194 p.expect("\r")?; 211 Relay<'static>,
195 p.expect("logged in as fred\r\n")?; 212 Relay<'static>,
196 p.expect("posting 1 pull request with 2 commits...\r\n")?; 213 Relay<'static>,
214 Relay<'static>,
215 Relay<'static>,
216)> {
217 let git_repo = prep_git_repo()?;
218 // fallback (51,52) user write (53, 55) repo (55, 56)
219 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
220 Relay::new(
221 8051,
222 None,
223 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
224 relay.respond_events(
225 client_id,
226 &subscription_id,
227 &vec![
228 generate_test_key_1_metadata_event("fred"),
229 generate_test_key_1_relay_list_event(),
230 ],
231 )?;
232 Ok(())
233 }),
234 ),
235 Relay::new(8052, None, None),
236 Relay::new(8053, None, None),
237 Relay::new(
238 8055,
239 None,
240 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
241 relay.respond_events(
242 client_id,
243 &subscription_id,
244 &vec![generate_repo_ref_event()],
245 )?;
246 Ok(())
247 }),
248 ),
249 Relay::new(8056, None, None),
250 );
251
252 // // check relay had the right number of events
253 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
254 let mut p = cli_tester_create_pr(&git_repo, include_cover_letter);
255 p.expect_end_eventually()?;
256 for p in [51, 52, 53, 55, 56] {
257 relay::shutdown_relay(8000 + p)?;
258 }
197 Ok(()) 259 Ok(())
198 } 260 });
261
262 // launch relay
263 let _ = join!(
264 r51.listen_until_close(),
265 r52.listen_until_close(),
266 r53.listen_until_close(),
267 r55.listen_until_close(),
268 r56.listen_until_close(),
269 );
270 cli_tester_handle.join().unwrap()?;
271 Ok((r51, r52, r53, r55, r56))
272}
199 273
200 async fn prep_run_create_pr() -> Result<( 274mod sends_cover_letter_and_2_patches_to_3_relays {
201 Relay<'static>,
202 Relay<'static>,
203 Relay<'static>,
204 Relay<'static>,
205 Relay<'static>,
206 )> {
207 let git_repo = prep_git_repo()?;
208 // fallback (51,52) user write (53, 55) repo (55, 56)
209 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
210 Relay::new(
211 8051,
212 None,
213 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
214 relay.respond_events(
215 client_id,
216 &subscription_id,
217 &vec![
218 generate_test_key_1_metadata_event("fred"),
219 generate_test_key_1_relay_list_event(),
220 ],
221 )?;
222 Ok(())
223 }),
224 ),
225 Relay::new(8052, None, None),
226 Relay::new(8053, None, None),
227 Relay::new(
228 8055,
229 None,
230 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
231 relay.respond_events(
232 client_id,
233 &subscription_id,
234 &vec![generate_repo_ref_event()],
235 )?;
236 Ok(())
237 }),
238 ),
239 Relay::new(8056, None, None),
240 );
241
242 // // check relay had the right number of events
243 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
244 let mut p = cli_tester_create_pr(&git_repo);
245 p.expect_end_eventually()?;
246 for p in [51, 52, 53, 55, 56] {
247 relay::shutdown_relay(8000 + p)?;
248 }
249 Ok(())
250 });
251
252 // launch relay
253 let _ = join!(
254 r51.listen_until_close(),
255 r52.listen_until_close(),
256 r53.listen_until_close(),
257 r55.listen_until_close(),
258 r56.listen_until_close(),
259 );
260 cli_tester_handle.join().unwrap()?;
261 Ok((r51, r52, r53, r55, r56))
262 }
263 275
276 use super::*;
264 #[tokio::test] 277 #[tokio::test]
265 #[serial] 278 #[serial]
266 async fn only_1_pr_kind_event_sent_to_each_relay() -> Result<()> { 279 async fn only_1_pr_kind_event_sent_to_each_relay() -> Result<()> {
267 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 280 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
268 for relay in [&r53, &r55, &r56] { 281 for relay in [&r53, &r55, &r56] {
269 assert_eq!( 282 assert_eq!(
270 relay.events.iter().filter(|e| is_cover_letter(e)).count(), 283 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
@@ -277,7 +290,7 @@ mod sends_pr_and_2_patches_to_3_relays {
277 #[tokio::test] 290 #[tokio::test]
278 #[serial] 291 #[serial]
279 async fn only_1_pr_kind_event_sent_to_user_relays() -> Result<()> { 292 async fn only_1_pr_kind_event_sent_to_user_relays() -> Result<()> {
280 let (_, _, r53, r55, _) = prep_run_create_pr().await?; 293 let (_, _, r53, r55, _) = prep_run_create_pr(true).await?;
281 for relay in [&r53, &r55] { 294 for relay in [&r53, &r55] {
282 assert_eq!( 295 assert_eq!(
283 relay.events.iter().filter(|e| is_cover_letter(e)).count(), 296 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
@@ -290,7 +303,7 @@ mod sends_pr_and_2_patches_to_3_relays {
290 #[tokio::test] 303 #[tokio::test]
291 #[serial] 304 #[serial]
292 async fn only_1_pr_kind_event_sent_to_repo_relays() -> Result<()> { 305 async fn only_1_pr_kind_event_sent_to_repo_relays() -> Result<()> {
293 let (_, _, _, r55, r56) = prep_run_create_pr().await?; 306 let (_, _, _, r55, r56) = prep_run_create_pr(true).await?;
294 for relay in [&r55, &r56] { 307 for relay in [&r55, &r56] {
295 assert_eq!( 308 assert_eq!(
296 relay.events.iter().filter(|e| is_cover_letter(e)).count(), 309 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
@@ -303,7 +316,7 @@ mod sends_pr_and_2_patches_to_3_relays {
303 #[tokio::test] 316 #[tokio::test]
304 #[serial] 317 #[serial]
305 async fn pr_not_sent_to_fallback_relay() -> Result<()> { 318 async fn pr_not_sent_to_fallback_relay() -> Result<()> {
306 let (r51, r52, _, _, _) = prep_run_create_pr().await?; 319 let (r51, r52, _, _, _) = prep_run_create_pr(true).await?;
307 for relay in [&r51, &r52] { 320 for relay in [&r51, &r52] {
308 assert_eq!( 321 assert_eq!(
309 relay.events.iter().filter(|e| is_cover_letter(e)).count(), 322 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
@@ -316,7 +329,7 @@ mod sends_pr_and_2_patches_to_3_relays {
316 #[tokio::test] 329 #[tokio::test]
317 #[serial] 330 #[serial]
318 async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { 331 async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> {
319 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 332 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
320 for relay in [&r53, &r55, &r56] { 333 for relay in [&r53, &r55, &r56] {
321 assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,); 334 assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,);
322 } 335 }
@@ -327,18 +340,18 @@ mod sends_pr_and_2_patches_to_3_relays {
327 #[serial] 340 #[serial]
328 async fn patch_content_contains_patch_in_email_format_with_patch_series_numbers() -> Result<()> 341 async fn patch_content_contains_patch_in_email_format_with_patch_series_numbers() -> Result<()>
329 { 342 {
330 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 343 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
331 for relay in [&r53, &r55, &r56] { 344 for relay in [&r53, &r55, &r56] {
332 let patch_events: Vec<&nostr::Event> = 345 let patch_events: Vec<&nostr::Event> =
333 relay.events.iter().filter(|e| is_patch(e)).collect(); 346 relay.events.iter().filter(|e| is_patch(e)).collect();
334 347
335 assert_eq!( 348 assert_eq!(
336 patch_events[0].content, 349 patch_events[1].content,
337 "\ 350 "\
338 From fe973a840fba2a8ab37dd505c154854a69a6505c Mon Sep 17 00:00:00 2001\n\ 351 From fe973a840fba2a8ab37dd505c154854a69a6505c Mon Sep 17 00:00:00 2001\n\
339 From: Joe Bloggs <joe.bloggs@pm.me>\n\ 352 From: Joe Bloggs <joe.bloggs@pm.me>\n\
340 Date: Thu, 1 Jan 1970 00:00:00 +0000\n\ 353 Date: Thu, 1 Jan 1970 00:00:00 +0000\n\
341 Subject: [PATCH 1/2] add t4.md\n\ 354 Subject: [PATCH 2/2] add t4.md\n\
342 \n\ 355 \n\
343 ---\n \ 356 ---\n \
344 t4.md | 1 +\n \ 357 t4.md | 1 +\n \
@@ -359,12 +372,12 @@ mod sends_pr_and_2_patches_to_3_relays {
359 ", 372 ",
360 ); 373 );
361 assert_eq!( 374 assert_eq!(
362 patch_events[1].content, 375 patch_events[0].content,
363 "\ 376 "\
364 From 232efb37ebc67692c9e9ff58b83c0d3d63971a0a Mon Sep 17 00:00:00 2001\n\ 377 From 232efb37ebc67692c9e9ff58b83c0d3d63971a0a Mon Sep 17 00:00:00 2001\n\
365 From: Joe Bloggs <joe.bloggs@pm.me>\n\ 378 From: Joe Bloggs <joe.bloggs@pm.me>\n\
366 Date: Thu, 1 Jan 1970 00:00:00 +0000\n\ 379 Date: Thu, 1 Jan 1970 00:00:00 +0000\n\
367 Subject: [PATCH 2/2] add t3.md\n\ 380 Subject: [PATCH 1/2] add t3.md\n\
368 \n\ 381 \n\
369 ---\n \ 382 ---\n \
370 t3.md | 1 +\n \ 383 t3.md | 1 +\n \
@@ -394,7 +407,7 @@ mod sends_pr_and_2_patches_to_3_relays {
394 #[tokio::test] 407 #[tokio::test]
395 #[serial] 408 #[serial]
396 async fn root_commit_as_r() -> Result<()> { 409 async fn root_commit_as_r() -> Result<()> {
397 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 410 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
398 for relay in [&r53, &r55, &r56] { 411 for relay in [&r53, &r55, &r56] {
399 let pr_event: &nostr::Event = 412 let pr_event: &nostr::Event =
400 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 413 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
@@ -414,7 +427,7 @@ mod sends_pr_and_2_patches_to_3_relays {
414 #[tokio::test] 427 #[tokio::test]
415 #[serial] 428 #[serial]
416 async fn a_tag_for_repo_event() -> Result<()> { 429 async fn a_tag_for_repo_event() -> Result<()> {
417 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 430 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
418 for relay in [&r53, &r55, &r56] { 431 for relay in [&r53, &r55, &r56] {
419 let pr_event: &nostr::Event = 432 let pr_event: &nostr::Event =
420 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 433 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
@@ -436,7 +449,7 @@ mod sends_pr_and_2_patches_to_3_relays {
436 .unwrap() 449 .unwrap()
437 .as_vec() 450 .as_vec()
438 .clone()[1..]; 451 .clone()[1..];
439 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 452 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
440 for relay in [&r53, &r55, &r56] { 453 for relay in [&r53, &r55, &r56] {
441 for m in maintainers { 454 for m in maintainers {
442 let pr_event: &nostr::Event = 455 let pr_event: &nostr::Event =
@@ -454,7 +467,7 @@ mod sends_pr_and_2_patches_to_3_relays {
454 #[tokio::test] 467 #[tokio::test]
455 #[serial] 468 #[serial]
456 async fn t_tag_cover_letter() -> Result<()> { 469 async fn t_tag_cover_letter() -> Result<()> {
457 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 470 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
458 for relay in [&r53, &r55, &r56] { 471 for relay in [&r53, &r55, &r56] {
459 let pr_event: &nostr::Event = 472 let pr_event: &nostr::Event =
460 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 473 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
@@ -470,7 +483,7 @@ mod sends_pr_and_2_patches_to_3_relays {
470 #[tokio::test] 483 #[tokio::test]
471 #[serial] 484 #[serial]
472 async fn t_tag_root() -> Result<()> { 485 async fn t_tag_root() -> Result<()> {
473 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 486 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
474 for relay in [&r53, &r55, &r56] { 487 for relay in [&r53, &r55, &r56] {
475 let pr_event: &nostr::Event = 488 let pr_event: &nostr::Event =
476 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 489 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
@@ -486,7 +499,7 @@ mod sends_pr_and_2_patches_to_3_relays {
486 #[tokio::test] 499 #[tokio::test]
487 #[serial] 500 #[serial]
488 async fn pr_tags_branch_name() -> Result<()> { 501 async fn pr_tags_branch_name() -> Result<()> {
489 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 502 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
490 for relay in [&r53, &r55, &r56] { 503 for relay in [&r53, &r55, &r56] {
491 let pr_event: &nostr::Event = 504 let pr_event: &nostr::Event =
492 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 505 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
@@ -509,14 +522,14 @@ mod sends_pr_and_2_patches_to_3_relays {
509 use super::*; 522 use super::*;
510 523
511 async fn prep() -> Result<nostr::Event> { 524 async fn prep() -> Result<nostr::Event> {
512 let (_, _, r53, _, _) = prep_run_create_pr().await?; 525 let (_, _, r53, _, _) = prep_run_create_pr(true).await?;
513 Ok(r53.events.iter().find(|e| is_patch(e)).unwrap().clone()) 526 Ok(r53.events.iter().find(|e| is_patch(e)).unwrap().clone())
514 } 527 }
515 528
516 #[tokio::test] 529 #[tokio::test]
517 #[serial] 530 #[serial]
518 async fn commit_and_commit_r() -> Result<()> { 531 async fn commit_and_commit_r() -> Result<()> {
519 static COMMIT_ID: &str = "fe973a840fba2a8ab37dd505c154854a69a6505c"; 532 static COMMIT_ID: &str = "232efb37ebc67692c9e9ff58b83c0d3d63971a0a";
520 let most_recent_patch = prep().await?; 533 let most_recent_patch = prep().await?;
521 assert!( 534 assert!(
522 most_recent_patch 535 most_recent_patch
@@ -537,12 +550,16 @@ mod sends_pr_and_2_patches_to_3_relays {
537 #[serial] 550 #[serial]
538 async fn parent_commit() -> Result<()> { 551 async fn parent_commit() -> Result<()> {
539 // commit parent 'r' and 'parent-commit' tag 552 // commit parent 'r' and 'parent-commit' tag
540 static COMMIT_PARENT_ID: &str = "232efb37ebc67692c9e9ff58b83c0d3d63971a0a"; 553 static COMMIT_PARENT_ID: &str = "431b84edc0d2fa118d63faa3c2db9c73d630a5ae";
541 let most_recent_patch = prep().await?; 554 let most_recent_patch = prep().await?;
542 assert!( 555 assert_eq!(
543 most_recent_patch.tags.iter().any( 556 most_recent_patch
544 |t| t.as_vec()[0].eq("parent-commit") && t.as_vec()[1].eq(COMMIT_PARENT_ID) 557 .tags
545 ) 558 .iter()
559 .find(|t| t.as_vec()[0].eq("parent-commit"))
560 .unwrap()
561 .as_vec()[1],
562 COMMIT_PARENT_ID,
546 ); 563 );
547 Ok(()) 564 Ok(())
548 } 565 }
@@ -599,7 +616,7 @@ mod sends_pr_and_2_patches_to_3_relays {
599 .find(|t| t.as_vec()[0].eq("description")) 616 .find(|t| t.as_vec()[0].eq("description"))
600 .unwrap() 617 .unwrap()
601 .as_vec()[1], 618 .as_vec()[1],
602 "add t4.md" 619 "add t3.md"
603 ); 620 );
604 Ok(()) 621 Ok(())
605 } 622 }
@@ -639,7 +656,7 @@ mod sends_pr_and_2_patches_to_3_relays {
639 #[tokio::test] 656 #[tokio::test]
640 #[serial] 657 #[serial]
641 async fn patch_tags_pr_event_as_root() -> Result<()> { 658 async fn patch_tags_pr_event_as_root() -> Result<()> {
642 let (_, _, r53, r55, r56) = prep_run_create_pr().await?; 659 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
643 for relay in [&r53, &r55, &r56] { 660 for relay in [&r53, &r55, &r56] {
644 let patch_events: Vec<&nostr::Event> = 661 let patch_events: Vec<&nostr::Event> =
645 relay.events.iter().filter(|e| is_patch(e)).collect(); 662 relay.events.iter().filter(|e| is_patch(e)).collect();
@@ -659,6 +676,43 @@ mod sends_pr_and_2_patches_to_3_relays {
659 } 676 }
660 Ok(()) 677 Ok(())
661 } 678 }
679
680 #[tokio::test]
681 #[serial]
682 async fn second_patch_tags_first_with_reply() -> Result<()> {
683 let (_, _, r53, r55, r56) = prep_run_create_pr(true).await?;
684 for relay in [&r53, &r55, &r56] {
685 let patch_events = relay
686 .events
687 .iter()
688 .filter(|e| is_patch(e))
689 .collect::<Vec<&nostr::Event>>();
690 assert_eq!(
691 patch_events[1]
692 .iter_tags()
693 .find(|t| t.as_vec()[0].eq("e")
694 && t.as_vec().len().eq(&4)
695 && t.as_vec()[3].eq("reply"))
696 .unwrap()
697 .as_vec()[1],
698 patch_events[0].id.to_string(),
699 );
700 }
701 Ok(())
702 }
703
704 #[tokio::test]
705 #[serial]
706 async fn no_t_root_tag() -> Result<()> {
707 assert!(
708 !prep()
709 .await?
710 .tags
711 .iter()
712 .any(|t| t.as_vec()[0].eq("t") && t.as_vec()[1].eq("root"))
713 );
714 Ok(())
715 }
662 } 716 }
663 mod cli_ouput { 717 mod cli_ouput {
664 use super::*; 718 use super::*;
@@ -701,8 +755,8 @@ mod sends_pr_and_2_patches_to_3_relays {
701 755
702 // // check relay had the right number of events 756 // // check relay had the right number of events
703 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 757 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
704 let mut p = cli_tester_create_pr(&git_repo); 758 let mut p = cli_tester_create_pr(&git_repo, true);
705 expect_msgs_first(&mut p)?; 759 expect_msgs_first(&mut p, true)?;
706 relay::expect_send_with_progress( 760 relay::expect_send_with_progress(
707 &mut p, 761 &mut p,
708 vec![ 762 vec![
@@ -790,7 +844,7 @@ mod sends_pr_and_2_patches_to_3_relays {
790 844
791 // // check relay had the right number of events 845 // // check relay had the right number of events
792 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 846 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
793 let mut p = cli_tester_create_pr(&git_repo); 847 let mut p = cli_tester_create_pr(&git_repo, true);
794 p.expect_end_eventually()?; 848 p.expect_end_eventually()?;
795 for p in [51, 52, 53, 55, 56] { 849 for p in [51, 52, 53, 55, 56] {
796 relay::shutdown_relay(8000 + p)?; 850 relay::shutdown_relay(8000 + p)?;
@@ -869,8 +923,8 @@ mod sends_pr_and_2_patches_to_3_relays {
869 923
870 // // check relay had the right number of events 924 // // check relay had the right number of events
871 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 925 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
872 let mut p = cli_tester_create_pr(&git_repo); 926 let mut p = cli_tester_create_pr(&git_repo, true);
873 expect_msgs_first(&mut p)?; 927 expect_msgs_first(&mut p, true)?;
874 // p.expect_end_with("bla")?; 928 // p.expect_end_with("bla")?;
875 relay::expect_send_with_progress( 929 relay::expect_send_with_progress(
876 &mut p, 930 &mut p,
@@ -915,7 +969,162 @@ mod sends_pr_and_2_patches_to_3_relays {
915 } 969 }
916} 970}
917 971
918mod without_cover_letter { 972mod sends_2_patches_without_cover_letter {
919 use super::*; 973 use super::*;
920 // TODO 974
975 mod cli_ouput {
976 use super::*;
977
978 async fn run_test_async() -> Result<()> {
979 let git_repo = prep_git_repo()?;
980
981 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
982 Relay::new(
983 8051,
984 None,
985 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
986 relay.respond_events(
987 client_id,
988 &subscription_id,
989 &vec![
990 generate_test_key_1_metadata_event("fred"),
991 generate_test_key_1_relay_list_event(),
992 ],
993 )?;
994 Ok(())
995 }),
996 ),
997 Relay::new(8052, None, None),
998 Relay::new(8053, None, None),
999 Relay::new(
1000 8055,
1001 None,
1002 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1003 relay.respond_events(
1004 client_id,
1005 &subscription_id,
1006 &vec![generate_repo_ref_event()],
1007 )?;
1008 Ok(())
1009 }),
1010 ),
1011 Relay::new(8056, None, None),
1012 );
1013
1014 // // check relay had the right number of events
1015 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
1016 let mut p = cli_tester_create_pr(&git_repo, false);
1017
1018 expect_msgs_first(&mut p, false)?;
1019 relay::expect_send_with_progress(
1020 &mut p,
1021 vec![
1022 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
1023 (" [my-relay] ws://localhost:8053", true, ""),
1024 (" [repo-relay] ws://localhost:8056", true, ""),
1025 ],
1026 2,
1027 )?;
1028 p.expect_end_with_whitespace()?;
1029 for p in [51, 52, 53, 55, 56] {
1030 relay::shutdown_relay(8000 + p)?;
1031 }
1032 Ok(())
1033 });
1034
1035 // launch relay
1036 let _ = join!(
1037 r51.listen_until_close(),
1038 r52.listen_until_close(),
1039 r53.listen_until_close(),
1040 r55.listen_until_close(),
1041 r56.listen_until_close(),
1042 );
1043 cli_tester_handle.join().unwrap()?;
1044 Ok(())
1045 }
1046
1047 #[tokio::test]
1048 #[serial]
1049 async fn check_cli_output() -> Result<()> {
1050 run_test_async().await?;
1051 Ok(())
1052 }
1053 }
1054
1055 #[tokio::test]
1056 #[serial]
1057 async fn no_cover_letter_event() -> Result<()> {
1058 let (_, _, r53, r55, r56) = prep_run_create_pr(false).await?;
1059 for relay in [&r53, &r55, &r56] {
1060 assert_eq!(
1061 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
1062 0,
1063 );
1064 }
1065 Ok(())
1066 }
1067
1068 #[tokio::test]
1069 #[serial]
1070 async fn two_patch_events() -> Result<()> {
1071 let (_, _, r53, r55, r56) = prep_run_create_pr(false).await?;
1072 for relay in [&r53, &r55, &r56] {
1073 assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2);
1074 }
1075 Ok(())
1076 }
1077
1078 #[tokio::test]
1079 #[serial]
1080 // TODO check this is the ancestor
1081 async fn first_patch_with_root_t_tag() -> Result<()> {
1082 let (_, _, r53, r55, r56) = prep_run_create_pr(false).await?;
1083 for relay in [&r53, &r55, &r56] {
1084 let patch_events = relay
1085 .events
1086 .iter()
1087 .filter(|e| is_patch(e))
1088 .collect::<Vec<&nostr::Event>>();
1089
1090 // first patch tagged as root
1091 assert!(
1092 patch_events[0]
1093 .iter_tags()
1094 .any(|t| t.as_vec()[0].eq("t") && t.as_vec()[1].eq("root"))
1095 );
1096 // second patch not tagged as root
1097 assert!(
1098 !patch_events[1]
1099 .iter_tags()
1100 .any(|t| t.as_vec()[0].eq("t") && t.as_vec()[1].eq("root"))
1101 );
1102 }
1103 Ok(())
1104 }
1105
1106 #[tokio::test]
1107 #[serial]
1108 async fn second_patch_lists_first_as_root() -> Result<()> {
1109 let (_, _, r53, r55, r56) = prep_run_create_pr(false).await?;
1110 for relay in [&r53, &r55, &r56] {
1111 let patch_events = relay
1112 .events
1113 .iter()
1114 .filter(|e| is_patch(e))
1115 .collect::<Vec<&nostr::Event>>();
1116
1117 assert_eq!(
1118 patch_events[1]
1119 .iter_tags()
1120 .find(|t| t.as_vec()[0].eq("e")
1121 && t.as_vec().len().eq(&4)
1122 && t.as_vec()[3].eq("root"))
1123 .unwrap()
1124 .as_vec()[1],
1125 patch_events[0].id.to_string(),
1126 );
1127 }
1128 Ok(())
1129 }
921} 1130}
diff --git a/tests/prs_list.rs b/tests/prs_list.rs
index 75704f6..7c0d8ec 100644
--- a/tests/prs_list.rs
+++ b/tests/prs_list.rs
@@ -6,6 +6,7 @@ use test_utils::{git::GitTestRepo, relay::Relay, *};
6static FEATURE_BRANCH_NAME_1: &str = "feature-example-t"; 6static FEATURE_BRANCH_NAME_1: &str = "feature-example-t";
7static FEATURE_BRANCH_NAME_2: &str = "feature-example-f"; 7static FEATURE_BRANCH_NAME_2: &str = "feature-example-f";
8static FEATURE_BRANCH_NAME_3: &str = "feature-example-c"; 8static FEATURE_BRANCH_NAME_3: &str = "feature-example-c";
9static FEATURE_BRANCH_NAME_4: &str = "feature-example-d";
9 10
10static PR_TITLE_1: &str = "pr a"; 11static PR_TITLE_1: &str = "pr a";
11static PR_TITLE_2: &str = "pr b"; 12static PR_TITLE_2: &str = "pr b";
@@ -18,22 +19,19 @@ fn cli_tester_create_prs() -> Result<GitTestRepo> {
18 &git_repo, 19 &git_repo,
19 FEATURE_BRANCH_NAME_1, 20 FEATURE_BRANCH_NAME_1,
20 "a", 21 "a",
21 PR_TITLE_1, 22 Some((PR_TITLE_1, "pr a description")),
22 "pr a description",
23 )?; 23 )?;
24 cli_tester_create_pr( 24 cli_tester_create_pr(
25 &git_repo, 25 &git_repo,
26 FEATURE_BRANCH_NAME_2, 26 FEATURE_BRANCH_NAME_2,
27 "b", 27 "b",
28 PR_TITLE_2, 28 Some((PR_TITLE_2, "pr b description")),
29 "pr b description",
30 )?; 29 )?;
31 cli_tester_create_pr( 30 cli_tester_create_pr(
32 &git_repo, 31 &git_repo,
33 FEATURE_BRANCH_NAME_3, 32 FEATURE_BRANCH_NAME_3,
34 "c", 33 "c",
35 PR_TITLE_3, 34 Some((PR_TITLE_3, "pr c description")),
36 "pr c description",
37 )?; 35 )?;
38 Ok(git_repo) 36 Ok(git_repo)
39} 37}
@@ -66,28 +64,44 @@ fn cli_tester_create_pr(
66 test_repo: &GitTestRepo, 64 test_repo: &GitTestRepo,
67 branch_name: &str, 65 branch_name: &str,
68 prefix: &str, 66 prefix: &str,
69 title: &str, 67 cover_letter_title_and_description: Option<(&str, &str)>,
70 description: &str,
71) -> Result<()> { 68) -> Result<()> {
72 create_and_populate_branch(test_repo, branch_name, prefix, false)?; 69 create_and_populate_branch(test_repo, branch_name, prefix, false)?;
73 70
74 let mut p = CliTester::new_from_dir( 71 if let Some((title, description)) = cover_letter_title_and_description {
75 &test_repo.dir, 72 let mut p = CliTester::new_from_dir(
76 [ 73 &test_repo.dir,
77 "--nsec", 74 [
78 TEST_KEY_1_NSEC, 75 "--nsec",
79 "--password", 76 TEST_KEY_1_NSEC,
80 TEST_PASSWORD, 77 "--password",
81 "--disable-cli-spinners", 78 TEST_PASSWORD,
82 "prs", 79 "--disable-cli-spinners",
83 "create", 80 "prs",
84 "--title", 81 "create",
85 format!("\"{title}\"").as_str(), 82 "--title",
86 "--description", 83 format!("\"{title}\"").as_str(),
87 format!("\"{description}\"").as_str(), 84 "--description",
88 ], 85 format!("\"{description}\"").as_str(),
89 ); 86 ],
90 p.expect_end_eventually()?; 87 );
88 p.expect_end_eventually()?;
89 } else {
90 let mut p = CliTester::new_from_dir(
91 &test_repo.dir,
92 [
93 "--nsec",
94 TEST_KEY_1_NSEC,
95 "--password",
96 TEST_PASSWORD,
97 "--disable-cli-spinners",
98 "prs",
99 "create",
100 "--no-cover-letter",
101 ],
102 );
103 p.expect_end_eventually()?;
104 }
91 Ok(()) 105 Ok(())
92} 106}
93 107
@@ -432,6 +446,183 @@ mod when_main_branch_is_uptodate {
432 Ok(()) 446 Ok(())
433 } 447 }
434 } 448 }
449 mod when_forth_pr_has_no_cover_letter {
450 use super::*;
451
452 async fn prep_and_run() -> Result<(GitTestRepo, GitTestRepo)> {
453 // fallback (51,52) user write (53, 55) repo (55, 56)
454 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
455 Relay::new(8051, None, None),
456 Relay::new(8052, None, None),
457 Relay::new(8053, None, None),
458 Relay::new(8055, None, None),
459 Relay::new(8056, None, None),
460 );
461
462 r51.events.push(generate_test_key_1_relay_list_event());
463 r51.events.push(generate_test_key_1_metadata_event("fred"));
464 r51.events.push(generate_repo_ref_event());
465
466 r55.events.push(generate_repo_ref_event());
467 r55.events.push(generate_test_key_1_metadata_event("fred"));
468 r55.events.push(generate_test_key_1_relay_list_event());
469
470 let cli_tester_handle =
471 std::thread::spawn(move || -> Result<(GitTestRepo, GitTestRepo)> {
472 let originating_repo = cli_tester_create_prs()?;
473 cli_tester_create_pr(
474 &originating_repo,
475 FEATURE_BRANCH_NAME_4,
476 "d",
477 None,
478 )?;
479 let test_repo = GitTestRepo::default();
480 test_repo.populate()?;
481 let mut p = CliTester::new_from_dir(&test_repo.dir, ["prs", "list"]);
482
483 p.expect("finding PRs...\r\n")?;
484 let mut c = p.expect_choice(
485 "All PRs",
486 vec![
487 format!("\"{PR_TITLE_1}\""),
488 format!("\"{PR_TITLE_2}\""),
489 format!("\"{PR_TITLE_3}\""),
490 format!("add d3.md"), // commit msg title
491 ],
492 )?;
493 c.succeeds_with(3, true)?;
494 let mut confirm =
495 p.expect_confirm_eventually("check out branch?", Some(true))?;
496 confirm.succeeds_with(None)?;
497 p.expect_end_eventually_and_print()?;
498
499 for p in [51, 52, 53, 55, 56] {
500 relay::shutdown_relay(8000 + p)?;
501 }
502 Ok((originating_repo, test_repo))
503 });
504
505 // launch relay
506 let _ = join!(
507 r51.listen_until_close(),
508 r52.listen_until_close(),
509 r53.listen_until_close(),
510 r55.listen_until_close(),
511 r56.listen_until_close(),
512 );
513 let res = cli_tester_handle.join().unwrap()?;
514
515 Ok(res)
516 }
517
518 mod cli_prompts {
519 use super::*;
520 async fn run_async_prompts_to_choose_from_pr_titles() -> Result<()> {
521 let (mut r51, mut r52, mut r53, mut r55, mut r56) = (
522 Relay::new(8051, None, None),
523 Relay::new(8052, None, None),
524 Relay::new(8053, None, None),
525 Relay::new(8055, None, None),
526 Relay::new(8056, None, None),
527 );
528
529 r51.events.push(generate_test_key_1_relay_list_event());
530 r51.events.push(generate_test_key_1_metadata_event("fred"));
531 r51.events.push(generate_repo_ref_event());
532
533 r55.events.push(generate_repo_ref_event());
534 r55.events.push(generate_test_key_1_metadata_event("fred"));
535 r55.events.push(generate_test_key_1_relay_list_event());
536
537 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
538 let originating_repo = cli_tester_create_prs()?;
539 cli_tester_create_pr(
540 &originating_repo,
541 FEATURE_BRANCH_NAME_4,
542 "d",
543 None,
544 )?;
545 let test_repo = GitTestRepo::default();
546 test_repo.populate()?;
547 let mut p = CliTester::new_from_dir(&test_repo.dir, ["prs", "list"]);
548
549 p.expect("finding PRs...\r\n")?;
550 let mut c = p.expect_choice(
551 "All PRs",
552 vec![
553 format!("\"{PR_TITLE_1}\""),
554 format!("\"{PR_TITLE_2}\""),
555 format!("\"{PR_TITLE_3}\""),
556 format!("add d3.md"), // commit msg title
557 ],
558 )?;
559 c.succeeds_with(3, true)?;
560 p.expect("finding commits...\r\n")?;
561 let mut confirm = p.expect_confirm("check out branch?", Some(true))?;
562 confirm.succeeds_with(None)?;
563 p.expect("checked out PR branch. pulled 2 new commits\r\n")?;
564 p.expect_end()?;
565
566 for p in [51, 52, 53, 55, 56] {
567 relay::shutdown_relay(8000 + p)?;
568 }
569 Ok(())
570 });
571
572 // launch relay
573 let _ = join!(
574 r51.listen_until_close(),
575 r52.listen_until_close(),
576 r53.listen_until_close(),
577 r55.listen_until_close(),
578 r56.listen_until_close(),
579 );
580 cli_tester_handle.join().unwrap()?;
581 println!("{:?}", r55.events);
582 Ok(())
583 }
584
585 #[tokio::test]
586 #[serial]
587 async fn prompts_to_choose_from_pr_titles() -> Result<()> {
588 let _ = run_async_prompts_to_choose_from_pr_titles().await;
589 Ok(())
590 }
591 }
592
593 #[tokio::test]
594 #[serial]
595 async fn pr_branch_created_with_correct_name() -> Result<()> {
596 let (_, test_repo) = prep_and_run().await?;
597 assert_eq!(
598 vec![FEATURE_BRANCH_NAME_4, "main"],
599 test_repo.get_local_branch_names()?
600 );
601 Ok(())
602 }
603
604 #[tokio::test]
605 #[serial]
606 async fn pr_branch_checked_out() -> Result<()> {
607 let (_, test_repo) = prep_and_run().await?;
608 assert_eq!(
609 FEATURE_BRANCH_NAME_4,
610 test_repo.get_checked_out_branch_name()?,
611 );
612 Ok(())
613 }
614
615 #[tokio::test]
616 #[serial]
617 async fn pr_branch_tip_is_most_recent_patch() -> Result<()> {
618 let (originating_repo, test_repo) = prep_and_run().await?;
619 assert_eq!(
620 originating_repo.get_tip_of_local_branch(FEATURE_BRANCH_NAME_4)?,
621 test_repo.get_tip_of_local_branch(FEATURE_BRANCH_NAME_4)?,
622 );
623 Ok(())
624 }
625 }
435 } 626 }
436 } 627 }
437 628