forked from yvv/decision
Lot T4 : les tests d'avant suivent le seed de T4 sans rien perdre de ce qu'ils prouvent
Les tests qui lisaient F, N ou O rejouent leurs transitions sur le seed de M8 (tests/fixtures/seed-m8) : seed_quorum_texts, seed_rules, seed_proposals, api, quorum ; ils disent en plus que ces amendements sont dépassés par le retrait (superseded_by). Les comptes suivent le document de T4 : 27 articles, quatre Propositions seed (I1, E1, E12, E2), 33 modules à voter (27 articles, le titre, l'ordre de 5 sections). modules.rs : l'ordre sous vote se rejoue sur « conclusion » (K1, K2) ; « un ordre d'un seul article n'a rien à décider » sur une base née du seed de M8 (O1). seed_amend : tests unitaires de Version::SeedProposal et de la ligne seed_proposal (put_forward). order.rs ne lit que les colonnes d'avant 0012 : sections_now ne sert qu'à la naissance des modules, et article_amend n'en garde que les articles vivants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -146,8 +146,9 @@ async fn a_new_base_has_its_title_and_the_order_of_each_section() {
|
||||
c.login("Chiara").await;
|
||||
for group in ["monnaie-libre", "essai"] {
|
||||
let doc = c.doc(group).await;
|
||||
// The articles stay the articles: 33 of them, none of the modules.
|
||||
assert_eq!(doc["units"].as_array().expect("units").len(), 33, "{group}");
|
||||
// The articles stay the articles: 27 of them, none of the modules (since lot T4, the
|
||||
// rules of operation are out of the document, ADR 0014).
|
||||
assert_eq!(doc["units"].as_array().expect("units").len(), 27, "{group}");
|
||||
let title = &doc["modules"]["title"];
|
||||
assert_eq!(
|
||||
(title["kind"].as_str(), title["code"].as_str(), title["inertia"].as_u64()),
|
||||
@@ -163,27 +164,15 @@ async fn a_new_base_has_its_title_and_the_order_of_each_section() {
|
||||
// One order per section, in the order of the document, each at level 2.
|
||||
let orders = doc["modules"]["orders"].as_array().expect("orders");
|
||||
let sections: Vec<&str> = orders.iter().filter_map(|o| o["section"].as_str()).collect();
|
||||
assert_eq!(
|
||||
sections,
|
||||
[
|
||||
"introduction",
|
||||
"fondamental",
|
||||
"technique",
|
||||
"conclusion",
|
||||
"annexe",
|
||||
"formule",
|
||||
"inertie",
|
||||
"ordonnancement"
|
||||
]
|
||||
);
|
||||
assert_eq!(sections, ["introduction", "fondamental", "technique", "conclusion", "annexe"]);
|
||||
assert!(orders.iter().all(|o| o["inertia"] == 2 && o["inForce"]["seedMinimal"] == true));
|
||||
// Its version in force is the order the section reads in now.
|
||||
let fondamental = order_of(&doc, "fondamental");
|
||||
assert_eq!(codes(&doc, &fondamental["members"]), ["T1", "E1", "E2"]);
|
||||
assert_eq!(codes(&doc, &fondamental["members"]), ["T1", "E1", "E12", "E2"]);
|
||||
assert_eq!(fondamental["inForce"]["order"]["ids"], fondamental["members"]);
|
||||
assert_eq!(fondamental["moot"], false);
|
||||
// « Ordonnancement » holds one article: nothing to decide.
|
||||
assert_eq!(order_of(&doc, "ordonnancement")["moot"], true);
|
||||
// Every section holds two articles or more: each order has something to decide
|
||||
// (one of a single article: `an_order_of_one_article_has_nothing_to_decide`).
|
||||
assert!(orders.iter().all(|o| o["moot"] == false), "{group}");
|
||||
}
|
||||
// Born with them: the addition says so, once per document.
|
||||
let rows: Vec<(String, String)> = sqlx::query_as(
|
||||
@@ -197,11 +186,35 @@ async fn a_new_base_has_its_title_and_the_order_of_each_section() {
|
||||
let doc = c.doc("monnaie-libre").await;
|
||||
let id = doc["doc"]["id"].as_str().expect("id");
|
||||
let all = c.ok("GET", &format!("/api/docs/{id}/preview?mode=all"), None).await;
|
||||
assert_eq!(all["units"].as_array().expect("units").len(), 33);
|
||||
// The list of the group: the articles in force — none, I1, E1 and E2 are seed proposals
|
||||
// (ADR 0011), three more open versions —; no module has an open proposal yet.
|
||||
assert_eq!(all["units"].as_array().expect("units").len(), 27);
|
||||
// The list of the group: the articles in force — none, I1, E1, E12 and E2 are seed
|
||||
// proposals (ADR 0011) —, one open version per article and two more (E3, E7); no module
|
||||
// has an open proposal yet.
|
||||
let g = c.ok("GET", "/api/groups/monnaie-libre", None).await;
|
||||
assert_eq!((g["docs"][0]["inForce"].as_u64(), g["docs"][0]["open"].as_u64()), (Some(0), Some(35)));
|
||||
assert_eq!((g["docs"][0]["inForce"].as_u64(), g["docs"][0]["open"].as_u64()), (Some(0), Some(29)));
|
||||
}
|
||||
|
||||
/// The seed of M8 (tests/fixtures/seed-m8): « Ordonnancement » held one article, O1. Lot T4
|
||||
/// takes that section out of the document (ADR 0014); a base born on that seed still has it.
|
||||
fn m8_config() -> Config {
|
||||
let mut cfg = Config::for_tests();
|
||||
cfg.seed_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/seed-m8");
|
||||
cfg
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn an_order_of_one_article_has_nothing_to_decide() {
|
||||
let db = open_db("sqlite::memory:").await.expect("db");
|
||||
let state = AppState::new(m8_config(), db).await.expect("state");
|
||||
seed::ensure(&state).await.expect("seed");
|
||||
let mut c = Client::of(&state);
|
||||
c.login("Chiara").await;
|
||||
for group in ["monnaie-libre", "essai"] {
|
||||
let doc = c.doc(group).await;
|
||||
assert_eq!(codes(&doc, &order_of(&doc, "ordonnancement")["members"]), ["O1"], "{group}");
|
||||
assert_eq!(order_of(&doc, "ordonnancement")["moot"], true, "{group}");
|
||||
assert_eq!(order_of(&doc, "conclusion")["moot"], false, "{group}");
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -251,7 +264,7 @@ async fn an_order_is_proposed_with_the_articles_of_its_section_then_voted_into_f
|
||||
assert_eq!((back["status"].as_str(), back["origin"].as_str()), (Some("open"), Some("seed")));
|
||||
assert_eq!(codes(&doc, &back["order"]["ids"]), ["K1", "K2"]);
|
||||
// Nothing else moved: the other sections read as before, the texts are the same.
|
||||
assert_eq!(read_order(&doc, "fondamental"), ["T1", "E1", "E2"]);
|
||||
assert_eq!(read_order(&doc, "fondamental"), ["T1", "E1", "E12", "E2"]);
|
||||
assert_eq!(read_order(&doc, "technique")[0], "T2");
|
||||
}
|
||||
|
||||
@@ -259,12 +272,12 @@ async fn an_order_is_proposed_with_the_articles_of_its_section_then_voted_into_f
|
||||
async fn articles_that_enter_or_leave_a_section_complete_an_order_under_vote() {
|
||||
let (mut yvv, mut chiara, state) = two().await;
|
||||
// The order stays under vote with one voice.
|
||||
two_voices(&state, "ordre.inertie").await;
|
||||
two_voices(&state, "ordre.conclusion").await;
|
||||
let doc = yvv.doc("essai").await;
|
||||
let module = order_of(&doc, "inertie")["id"].as_str().expect("id").to_owned();
|
||||
let module = order_of(&doc, "conclusion")["id"].as_str().expect("id").to_owned();
|
||||
let doc_id = doc["doc"]["id"].as_str().expect("id").to_owned();
|
||||
let (n1, n11) = (id_of(&doc, "N1"), id_of(&doc, "N1.1"));
|
||||
let p = yvv.ok("POST", &format!("/api/units/{module}/order"), Some(json!({ "order": [n11, n1] }))).await["id"]
|
||||
let (k1, k2) = (id_of(&doc, "K1"), id_of(&doc, "K2"));
|
||||
let p = yvv.ok("POST", &format!("/api/units/{module}/order"), Some(json!({ "order": [k2, k1] }))).await["id"]
|
||||
.as_str()
|
||||
.expect("id")
|
||||
.to_owned();
|
||||
@@ -286,20 +299,22 @@ async fn articles_that_enter_or_leave_a_section_complete_an_order_under_vote() {
|
||||
.ok(
|
||||
"POST",
|
||||
&format!("/api/docs/{doc_id}/proposals"),
|
||||
Some(json!({ "section": "inertie", "title": "Inertie des modules", "body": "Le titre du document est à 4.", "submit": true })),
|
||||
Some(
|
||||
json!({ "section": "conclusion", "title": "Rappel", "body": "Un rappel pour finir.", "submit": true }),
|
||||
),
|
||||
)
|
||||
.await;
|
||||
let doc = yvv.doc("essai").await;
|
||||
let fresh = unit(&doc, "N1")["code"]
|
||||
let fresh = unit(&doc, "K1")["code"]
|
||||
.as_str()
|
||||
.map(|_| ())
|
||||
.and_then(|()| doc["units"].as_array().expect("u").iter().find(|u| u["id"] == created["unitId"]).cloned());
|
||||
let fresh = fresh.expect("the new article");
|
||||
let new_code = fresh["code"].as_str().expect("code").to_owned();
|
||||
assert_eq!(read_order(&doc, "inertie"), ["N1", "N1.1", new_code.as_str()], "a new article goes at the end");
|
||||
let module_now = order_of(&doc, "inertie");
|
||||
assert_eq!(read_order(&doc, "conclusion"), ["K1", "K2", new_code.as_str()], "a new article goes at the end");
|
||||
let module_now = order_of(&doc, "conclusion");
|
||||
let open = module_now["proposals"].as_array().expect("p").iter().find(|x| x["id"] == p.as_str()).expect("p");
|
||||
assert_eq!(codes(&doc, &open["order"]["ids"]), ["N1.1", "N1", new_code.as_str()]);
|
||||
assert_eq!(codes(&doc, &open["order"]["ids"]), ["K2", "K1", new_code.as_str()]);
|
||||
assert_eq!(codes(&doc, &open["order"]["added"]), [new_code.as_str()]);
|
||||
// Its vote stays: completing an order never asks the voters again.
|
||||
assert_eq!((open["tally"]["for"].as_u64(), open["myVote"].as_str()), (Some(1), Some("for")));
|
||||
@@ -307,47 +322,47 @@ async fn articles_that_enter_or_leave_a_section_complete_an_order_under_vote() {
|
||||
let added = created["id"].as_str().expect("id");
|
||||
chiara.ok("POST", &format!("/api/proposals/{added}/withdraw"), None).await;
|
||||
let doc = yvv.doc("essai").await;
|
||||
let open = order_of(&doc, "inertie")["proposals"]
|
||||
let open = order_of(&doc, "conclusion")["proposals"]
|
||||
.as_array()
|
||||
.expect("p")
|
||||
.iter()
|
||||
.find(|x| x["id"] == p.as_str())
|
||||
.cloned()
|
||||
.expect("p");
|
||||
assert_eq!(codes(&doc, &open["order"]["ids"]), ["N1.1", "N1"]);
|
||||
assert_eq!(codes(&doc, &open["order"]["ids"]), ["K2", "K1"]);
|
||||
assert!(open["order"]["added"].as_array().expect("a").is_empty());
|
||||
// An order proposed with three articles, one of which then leaves: dropped from it.
|
||||
let created = chiara
|
||||
.ok(
|
||||
"POST",
|
||||
&format!("/api/docs/{doc_id}/proposals"),
|
||||
Some(json!({ "section": "inertie", "title": "Autre", "body": "Un article de passage dans la section.", "submit": true })),
|
||||
Some(json!({ "section": "conclusion", "title": "Autre", "body": "Un article de passage dans la section.", "submit": true })),
|
||||
)
|
||||
.await;
|
||||
let other = created["unitId"].as_str().expect("unit").to_owned();
|
||||
let three = yvv.ok("POST", &format!("/api/units/{module}/order"), Some(json!({ "order": [other, n11, n1] }))).await
|
||||
let three = yvv.ok("POST", &format!("/api/units/{module}/order"), Some(json!({ "order": [other, k2, k1] }))).await
|
||||
["id"]
|
||||
.as_str()
|
||||
.expect("id")
|
||||
.to_owned();
|
||||
chiara.ok("POST", &format!("/api/proposals/{}/withdraw", created["id"].as_str().expect("id")), None).await;
|
||||
let doc = yvv.doc("essai").await;
|
||||
let o = order_of(&doc, "inertie")["proposals"]
|
||||
let o = order_of(&doc, "conclusion")["proposals"]
|
||||
.as_array()
|
||||
.expect("p")
|
||||
.iter()
|
||||
.find(|x| x["id"] == three.as_str())
|
||||
.cloned()
|
||||
.expect("o");
|
||||
assert_eq!(codes(&doc, &o["order"]["ids"]), ["N1.1", "N1"]);
|
||||
assert_eq!(codes(&doc, &o["order"]["ids"]), ["K2", "K1"]);
|
||||
assert_eq!(o["order"]["dropped"], json!([other]));
|
||||
// Completed, it reads like the first one: the second voice brings that order in.
|
||||
let v = chiara.vote(&p, "for").await;
|
||||
assert_eq!(v["entered"][0]["kind"], "order");
|
||||
let doc = yvv.doc("essai").await;
|
||||
assert_eq!(read_order(&doc, "inertie"), ["N1.1", "N1"]);
|
||||
assert_eq!(read_order(&doc, "conclusion"), ["K2", "K1"]);
|
||||
// Now the order in force: the other one changes nothing more and cannot enter.
|
||||
let o = order_of(&doc, "inertie")["proposals"]
|
||||
let o = order_of(&doc, "conclusion")["proposals"]
|
||||
.as_array()
|
||||
.expect("p")
|
||||
.iter()
|
||||
@@ -503,10 +518,10 @@ async fn a_new_article_goes_at_the_end_of_the_section_asked_for() {
|
||||
.to_owned()
|
||||
};
|
||||
let (ca, cb) = (code(&a), code(&b));
|
||||
assert_eq!(read_order(&doc, "fondamental"), ["T1", "E1", "E2", ca.as_str()]);
|
||||
assert_eq!(read_order(&doc, "fondamental"), ["T1", "E1", "E12", "E2", ca.as_str()]);
|
||||
assert_eq!(read_order(&doc, "introduction"), ["I1", "I2", cb.as_str()]);
|
||||
// It joins the order of its section, at its end.
|
||||
assert_eq!(codes(&doc, &order_of(&doc, "fondamental")["members"]), ["T1", "E1", "E2", ca.as_str()]);
|
||||
assert_eq!(codes(&doc, &order_of(&doc, "fondamental")["members"]), ["T1", "E1", "E12", "E2", ca.as_str()]);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user