Skip to content

Commit 57cf070

Browse files
committed
tests: add test for accepting an ownership invitation via token
1 parent 0f0e3ba commit 57cf070

File tree

1 file changed

+57
-1
lines changed

1 file changed

+57
-1
lines changed

src/tests/owners.rs

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use crate::{
22
add_team_to_crate,
33
builders::{CrateBuilder, PublishBuilder},
44
new_team,
5-
util::{MockCookieUser, MockTokenUser, RequestHelper},
5+
util::{MockAnonymousUser, MockCookieUser, MockTokenUser, RequestHelper},
66
TestApp,
77
};
88
use cargo_registry::{
99
models::Crate,
1010
views::{EncodableCrateOwnerInvitation, EncodableOwner, InvitationResponse},
11+
Emails,
1112
};
1213

1314
use conduit::StatusCode;
@@ -84,6 +85,19 @@ impl MockCookieUser {
8485
}
8586
}
8687

88+
impl MockAnonymousUser {
89+
fn accept_ownership_invitation_by_token(&self, token: &str) {
90+
#[derive(Deserialize)]
91+
struct Response {
92+
crate_owner_invitation: InvitationResponse,
93+
}
94+
95+
let url = format!("/api/v1/me/crate_owner_invitations/accept/{}", token);
96+
let response: Response = self.put(&url, &[]).good();
97+
assert!(response.crate_owner_invitation.accepted);
98+
}
99+
}
100+
87101
#[test]
88102
fn new_crate_owner() {
89103
let (app, _, _, token) = TestApp::full().with_token();
@@ -381,6 +395,31 @@ fn test_decline_invitation() {
381395
assert_eq!(json.users.len(), 1);
382396
}
383397

398+
#[test]
399+
fn test_accept_invitation_by_mail() {
400+
let (app, anon, owner, owner_token) = TestApp::init().with_token();
401+
let owner = owner.as_model();
402+
let invited_user = app.db_new_user("user_bar");
403+
let _krate = app.db(|conn| CrateBuilder::new("accept_invitation", owner.id).expect_build(conn));
404+
405+
// Invite a new owner
406+
owner_token.add_user_owner("accept_invitation", "user_bar");
407+
408+
// Retrieve the ownership invitation
409+
let invite_token = extract_token_from_invite_email(&app.as_inner().emails);
410+
411+
// Accept the invitation anonymously with a token
412+
anon.accept_ownership_invitation_by_token(&invite_token);
413+
414+
// New owner's invitation list should now be empty
415+
let json = invited_user.list_invitations();
416+
assert_eq!(json.crate_owner_invitations.len(), 0);
417+
418+
// New owner is now listed as an owner, so the crate has two owners
419+
let json = anon.show_crate_owners("accept_invitation");
420+
assert_eq!(json.users.len(), 2);
421+
}
422+
384423
#[test]
385424
fn inactive_users_dont_get_invitations() {
386425
use cargo_registry::models::NewUser;
@@ -437,3 +476,20 @@ fn highest_gh_id_is_most_recent_account_we_know_of() {
437476
let json = invited_user.list_invitations();
438477
assert_eq!(json.crate_owner_invitations.len(), 1);
439478
}
479+
480+
fn extract_token_from_invite_email(emails: &Emails) -> String {
481+
let message = emails
482+
.mails_in_memory()
483+
.unwrap()
484+
.into_iter()
485+
.find(|m| m.subject.contains("invitation"))
486+
.expect("missing email");
487+
488+
// Simple (but kinda fragile) parser to extract the token.
489+
let before_token = "/accept-invite/";
490+
let after_token = " ";
491+
let body = message.body.as_str();
492+
let before_pos = body.find(before_token).unwrap() + before_token.len();
493+
let after_pos = before_pos + (&body[before_pos..]).find(after_token).unwrap();
494+
body[before_pos..after_pos].to_string()
495+
}

0 commit comments

Comments
 (0)