~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/knotless

git that lives in your Atmosphere account

Forked from chadtmiller.com/knotless

0
0
116 lines · 5.2 KB Raw History
//! Choosing what one hears of from the pages: watching a repository, and
//! subscribing to or muting an issue, each kept by the appview for the
//! account alone, and shown back on the repository's and the issue's
//! pages.

use super::*;

/// The `name=value` of the session cookie a login set.
fn session(set: &[String]) -> String {
    let found = set.iter().find(|c| c.starts_with("knotless_session="));
    pair(found.unwrap()).to_string()
}

#[test]
fn watching_and_subscribing_from_the_pages() {
    // Started first, so its index sees the repositories made after.
    let server = gateway_with(None, true);
    let owner = person(account());
    let url = owner.url("watched");
    let work = owner.work("w", 1);
    owner.git(&work, &["push", "-q", &url, "main"]);
    let (code, issue) = owner.cli(&["issue", "create", &url, "Slow", "-m", "It is."], b"");
    assert_eq!(code, 0, "{issue}");
    let repo = format!("at://{}/dev.knotless.repo/watched", owner.account.did);
    let xrpc = |nsid: &str| format!("{}/xrpc/dev.knotless.{nsid}", server.base);
    let thread = |cookie: Option<&str>| {
        let url = format!("{}?repo={repo}&uri={issue}", xrpc("getThread"));
        browse("GET", &url, cookie, None, None).2
    };
    let get_repo = |cookie: Option<&str>| {
        let url = format!("{}?repo={repo}", xrpc("getRepo"));
        browse("GET", &url, cookie, None, None).2
    };
    let put = |cookie: Option<&str>, subject: &str, level: &str| {
        let body = json!({"subject": subject, "level": level});
        browse("POST", &xrpc("putSubscription"), cookie, None, Some(body))
    };
    let list = |cookie: Option<&str>, query: &str| {
        let url = format!("{}{query}", xrpc("listSubscriptions"));
        browse("GET", &url, cookie, None, None)
    };
    wait_until(|| thread(None)["item"]["title"] == "Slow");
    let watcher = person(account());
    let mine = session(&log_in(&server, &watcher.account, ""));
    let me = Some(mine.as_str());
    let theirs = session(&log_in(&server, &owner.account, ""));
    let owning = Some(theirs.as_str());

    // Nothing chosen: it hears of the issue only when mentioned, and its
    // author as its author.
    assert_eq!(thread(me)["viewer"].get("notifiedFor"), None);
    assert_eq!(thread(owning)["viewer"]["notifiedFor"], "author");
    assert_eq!(get_repo(me)["viewer"].get("subscription"), None);
    assert_eq!(list(me, "").2, json!({"subscriptions": []}));

    // Watching the repository, it hears of the issue as watching.
    let (status, _, now) = put(me, &repo, "all");
    assert_eq!(status, 200, "{now}");
    assert_eq!(
        (&now["subject"], &now["level"]),
        (&json!(repo), &json!("all"))
    );
    assert!(now["createdAt"].is_string());
    assert_eq!(get_repo(me)["viewer"]["subscription"], "all");
    assert_eq!(thread(me)["viewer"]["notifiedFor"], "watching");
    // Subscribed to the issue, then muted, as it chose.
    assert_eq!(put(me, &issue, "subscribed").2["level"], "subscribed");
    assert_eq!(thread(me)["viewer"]["subscription"], "subscribed");
    assert_eq!(put(me, &issue, "muted").2["level"], "muted");
    assert_eq!(thread(me)["viewer"]["subscription"], "muted");
    // Having commented, it hears of the thread as one who did.
    let said = json!({"repo": repo, "subject": issue, "body": "Same here."});
    let commented = browse("POST", &xrpc("createComment"), me, None, Some(said));
    assert_eq!(commented.0, 200, "{}", commented.2);
    assert_eq!(thread(me)["viewer"]["notifiedFor"], "commented");

    // Listed, the latest choice first, a page at a time.
    let all = list(me, "").2;
    let subjects: Vec<&str> = all["subscriptions"]
        .as_array()
        .unwrap()
        .iter()
        .map(|s| s["subject"].as_str().unwrap())
        .collect();
    assert_eq!(subjects, [issue.as_str(), repo.as_str()]);
    let first = list(me, "?limit=1").2;
    assert_eq!(first["subscriptions"].as_array().unwrap().len(), 1);
    assert_eq!(first["cursor"], "1");
    let next = list(me, "?limit=1&cursor=1").2;
    assert_eq!(next["subscriptions"][0]["subject"], repo.as_str());
    assert_eq!(next.get("cursor"), None);
    assert_eq!(list(me, "?cursor=x").0, 400);
    // Forgotten, as participating.
    let forgot = put(me, &repo, "participating").2;
    assert_eq!(forgot, json!({"subject": repo, "level": "participating"}));
    assert_eq!(get_repo(me)["viewer"].get("subscription"), None);

    // Refused: a level the subject cannot take, what is no repository,
    // pull or issue, a repository there is none of, no one asking, and
    // from another site.
    assert_eq!(put(me, &repo, "muted").0, 400);
    assert_eq!(put(me, &issue, "all").0, 400);
    let comment = commented.2["uri"].as_str().unwrap().to_string();
    assert_eq!(put(me, &comment, "subscribed").0, 400);
    assert_eq!(put(me, "nowhere", "all").0, 400);
    let gone = format!("at://{}/dev.knotless.repo/none", owner.account.did);
    assert_eq!(put(me, &gone, "all").0, 404);
    assert_eq!(put(None, &repo, "all").0, 401);
    assert_eq!(list(None, "").0, 401);
    let body = Some(json!({"subject": repo, "level": "all"}));
    let away = Some("https://evil.example");
    assert_eq!(
        browse("POST", &xrpc("putSubscription"), me, away, body).0,
        403
    );
}