//! Tests for local note reactions (like/announce) with proper authorization.
mod support;
use support::{Client, Server, free_port};
/// Register a user through the web form.
fn register(client: &mut Client, name: &str) {
let email = format!("{name}@example.org");
let response = client.post_form(
"/register",
&[
("name", name),
("email", &email),
("password", "correct horse battery staple"),
],
);
assert_eq!(
response.status, 303,
"registering should log in\n{}",
response.body
);
}
/// Extract note UUID from profile page HTML.
fn extract_note_uuid(html: &str, author: &str) -> Option<String> {
// Look for permalink pattern: href="http://.../~author/notes/{uuid}"
let pattern = format!("/~{author}/notes/");
let start = html.find(&pattern)?;
let after_pattern = &html[start + pattern.len()..];
let end = after_pattern.find('"')?;
Some(after_pattern[..end].to_string())
}
/// Test: Author cannot like their own note (server-side 403)
#[tokio::test]
async fn author_cannot_like_own_note() -> miette::Result<()> {
let port = free_port();
let mut server = Server::spawn_federated(&format!("127.0.0.1:{port}"));
server.wait_for_connection(port);
let mut alice_client = Client::new(port);
register(&mut alice_client, "alice");
// Post a note
let response = alice_client.post_form("/~alice/notes", &[("content", "My note")]);
assert_eq!(response.status, 303);
// Visit profile to get the note UUID
let response = alice_client.get("/~alice");
assert_eq!(response.status, 200);
let uuid =
extract_note_uuid(&response.body, "alice").expect("should find note UUID in profile");
// Try to react to own note - should fail with 403
let response = alice_client.post_form(&format!("/~alice/notes/{uuid}/react"), &[]);
assert_eq!(
response.status, 403,
"author should not be able to like their own note"
);
Ok(())
}
/// Test: Author CAN announce (boost) their own note
#[tokio::test]
async fn author_can_announce_own_note() -> miette::Result<()> {
let port = free_port();
let mut server = Server::spawn_federated(&format!("127.0.0.1:{port}"));
server.wait_for_connection(port);
let mut alice_client = Client::new(port);
register(&mut alice_client, "alice");
// Post a note
let response = alice_client.post_form("/~alice/notes", &[("content", "My note to boost")]);
assert_eq!(response.status, 303);
// Visit profile to get the note UUID
let response = alice_client.get("/~alice");
assert_eq!(response.status, 200);
let uuid =
extract_note_uuid(&response.body, "alice").expect("should find note UUID in profile");
// Author should be able to announce their own note
let response = alice_client.post_form(&format!("/~alice/notes/{uuid}/announce"), &[]);
assert_eq!(
response.status, 303,
"author should be able to announce their own note"
);
Ok(())
}
/// Test: User can like a note by another user
#[tokio::test]
async fn user_can_like_other_users_note() -> miette::Result<()> {
let port = free_port();
let mut server = Server::spawn_federated(&format!("127.0.0.1:{port}"));
server.wait_for_connection(port);
let mut alice_client = Client::new(port);
let mut bob_client = Client::new(port);
register(&mut alice_client, "alice");
register(&mut bob_client, "bob");
// Alice posts a note
let response = alice_client.post_form("/~alice/notes", &[("content", "Alice's note")]);
assert_eq!(response.status, 303);
// Visit Alice's profile to get the note UUID
let response = alice_client.get("/~alice");
assert_eq!(response.status, 200);
let uuid =
extract_note_uuid(&response.body, "alice").expect("should find note UUID in profile");
// Bob should be able to react to Alice's note
let response = bob_client.post_form(&format!("/~alice/notes/{uuid}/react"), &[]);
assert_eq!(
response.status, 303,
"non-author should be able to react to a note"
);
Ok(())
}