From aaa653e1a7820f7a6fd1d0c8b1c5f3c868850471 Mon Sep 17 00:00:00 2001 From: Yvv Date: Tue, 3 Nov 2026 04:12:20 +0100 Subject: [PATCH] Lot S : tests serveur repris sans Propositions seed en vigueur (modules, overview), rustfmt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit modules.rs : 0 article en vigueur et 35 propositions en cours dans une base neuve (I1, E1 et E2 sont des Propositions seed) ; l'ajout des modules à une base existante se rejoue sur le seed de production du 02/11 (textes en vigueur), comme inertia.rs. overview.rs : le vote porte sur la Proposition seed I1 ; 41 modules à voter, inchangé. Co-Authored-By: Claude Opus 5.5 --- crates/ld-server/src/seed.rs | 9 ++++----- crates/ld-server/src/seed_amend.rs | 6 +++++- crates/ld-server/tests/api.rs | 7 +++++-- crates/ld-server/tests/modules.rs | 25 +++++++++++++++++------- crates/ld-server/tests/overview.rs | 7 ++++--- crates/ld-server/tests/seed_proposals.rs | 14 ++++++++++--- crates/ld-server/tests/typos.rs | 3 ++- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/crates/ld-server/src/seed.rs b/crates/ld-server/src/seed.rs index c4ec844..ebf0609 100644 --- a/crates/ld-server/src/seed.rs +++ b/crates/ld-server/src/seed.rs @@ -198,7 +198,9 @@ fn check(seed: &SeedDoc) -> anyhow::Result<()> { anyhow::bail!("{}: a seed proposal is open, never in force", u.code); } match (u.puts_forward(), u.inertia.is_some()) { - (true, true) => anyhow::bail!("{}: a seed proposal starts at SEED_PROPOSAL_LEVEL, give it no level", u.code), + (true, true) => { + anyhow::bail!("{}: a seed proposal starts at SEED_PROPOSAL_LEVEL, give it no level", u.code) + } (false, false) => anyhow::bail!("{}: no level of inertia", u.code), _ => {} } @@ -273,10 +275,7 @@ async fn instantiate(state: &AppState, seed: &SeedDoc, inst: &SeedInstance) -> a .await?; // The mark, written apart: only where the seed puts the version forward. if v.seed_proposal && status == "open" { - sqlx::query("UPDATE proposals SET seed_featured = 1 WHERE id = ?") - .bind(&pid) - .execute(&mut *tx) - .await?; + sqlx::query("UPDATE proposals SET seed_featured = 1 WHERE id = ?").bind(&pid).execute(&mut *tx).await?; } if status == "in_force" { sqlx::query("UPDATE units SET in_force_id = ? WHERE id = ?") diff --git a/crates/ld-server/src/seed_amend.rs b/crates/ld-server/src/seed_amend.rs index 6bf0465..4ff8118 100644 --- a/crates/ld-server/src/seed_amend.rs +++ b/crates/ld-server/src/seed_amend.rs @@ -247,7 +247,11 @@ fn target_of<'a>(seeds: &'a [SeedDoc], a: &Amendment) -> Option<(&'a SeedDoc, &' } /// What the database says of a version holding `status` (`None`: it does not). -pub(crate) async fn facts(conn: &mut SqliteConnection, proposal_id: &str, status: &str) -> anyhow::Result> { +pub(crate) async fn facts( + conn: &mut SqliteConnection, + proposal_id: &str, + status: &str, +) -> anyhow::Result> { #[derive(sqlx::FromRow)] struct Row { origin: String, diff --git a/crates/ld-server/tests/api.rs b/crates/ld-server/tests/api.rs index 1fd036b..9aaeaf4 100644 --- a/crates/ld-server/tests/api.rs +++ b/crates/ld-server/tests/api.rs @@ -409,7 +409,10 @@ async fn inertia_change_is_voted_at_the_level_of_the_article() { assert_eq!(again["id"], p.as_str()); let (_, d) = a.call("GET", &format!("/api/proposals/{p}"), None).await; let low = u64::from(ld_server::seed::SEED_PROPOSAL_LEVEL); - assert_eq!((d["proposal"]["inertiaTarget"].as_u64(), d["proposal"]["votedAtInertia"].as_u64()), (Some(5), Some(low))); + assert_eq!( + (d["proposal"]["inertiaTarget"].as_u64(), d["proposal"]["votedAtInertia"].as_u64()), + (Some(5), Some(low)) + ); } #[tokio::test] @@ -843,7 +846,7 @@ async fn a_refused_first_push_goes_out_again_and_a_new_empty_repository_receives key: dir.join("data/keys/publish_ed25519"), author_name: "libreDecision".into(), author_email: "decision@example.org".into(), - without_articles: false, + without_articles: false, }); cfg }; diff --git a/crates/ld-server/tests/modules.rs b/crates/ld-server/tests/modules.rs index 8bf1fd3..77797cb 100644 --- a/crates/ld-server/tests/modules.rs +++ b/crates/ld-server/tests/modules.rs @@ -183,9 +183,10 @@ async fn a_new_base_has_its_title_and_the_order_of_each_section() { 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; no module has an open proposal yet. + // 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. 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(3), Some(32))); + assert_eq!((g["docs"][0]["inForce"].as_u64(), g["docs"][0]["open"].as_u64()), (Some(0), Some(35))); } #[tokio::test] @@ -250,7 +251,8 @@ async fn articles_that_enter_or_leave_a_section_complete_an_order_under_vote() { .expect("id") .to_owned(); yvv.vote(&p, "for").await; - // The list of the group counts it among the proposals in progress, never among the articles. + // The list of the group counts it among the proposals in progress, never among the articles + // (none in force: I1, E1 and E2 are seed proposals, ADR 0011). let g = yvv.ok("GET", "/api/groups/essai", None).await; let before = doc["units"] .as_array() @@ -259,7 +261,7 @@ async fn articles_that_enter_or_leave_a_section_complete_an_order_under_vote() { .map(|u| u["proposals"].as_array().expect("p").iter().filter(|x| x["status"] == "open").count() as u64); assert_eq!( (g["docs"][0]["inForce"].as_u64(), g["docs"][0]["open"].as_u64()), - (Some(3), Some(before.sum::() + 1)) + (Some(0), Some(before.sum::() + 1)) ); // A new article enters the section: at its end, and at the end of the order under vote. let created = chiara @@ -492,8 +494,17 @@ async fn a_new_article_goes_at_the_end_of_the_section_asked_for() { // A base born without modules, as production holds it, then the new version // --------------------------------------------------------------------------- +/// The seed production runs on 2026-11-02 (3f10a0e): I1, E1 and E2 in force, seeds a +/// minima. Since that day the seed puts them forward as seed proposals (ADR 0011, +/// tests/seed_proposals.rs); the addition of the modules is replayed on the seed of then. +fn production_config() -> Config { + let mut cfg = Config::for_tests(); + cfg.seed_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/seed-production-2026-11-02"); + cfg +} + fn seed_without_modules(tag: &str) -> std::path::PathBuf { - let today = Config::for_tests().seed_dir.join("acte-engagement-certification.json"); + let today = production_config().seed_dir.join("acte-engagement-certification.json"); let mut seed: Value = serde_json::from_str(&std::fs::read_to_string(today).expect("seed")).expect("json"); seed.as_object_mut().expect("object").remove("modules"); let dir = std::env::temp_dir().join(format!("ld-modules-seed-{tag}-{}", std::process::id())); @@ -554,7 +565,7 @@ async fn an_existing_document_receives_its_modules_once_from_what_it_holds() { let reads = read_order(&c.doc("essai").await, "conclusion"); // The new version starts: each document receives its modules, from what it holds. - let state = AppState::new(Config::for_tests(), before.db.clone()).await.expect("state"); + let state = AppState::new(production_config(), before.db.clone()).await.expect("state"); seed::ensure(&state).await.expect("seed"); let rows: Vec<(String, String, Option, Option)> = sqlx::query_as( "SELECT d.group_slug, m.outcome, m.reason, m.created FROM module_amendments m JOIN documents d ON d.id = m.doc_id @@ -619,7 +630,7 @@ async fn an_existing_document_receives_its_modules_once_from_what_it_holds() { assert_eq!(json["modules"]["orders"][1]["articles"], json!(["T1", "E1", "E2"])); // Once only: the next start adds nothing. - let again = AppState::new(Config::for_tests(), state.db.clone()).await.expect("state"); + let again = AppState::new(production_config(), state.db.clone()).await.expect("state"); seed::ensure(&again).await.expect("seed"); let n: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM units WHERE kind <> 'article'").fetch_one(&again.db).await.expect("n"); diff --git a/crates/ld-server/tests/overview.rs b/crates/ld-server/tests/overview.rs index 25701b7..7ab72c2 100644 --- a/crates/ld-server/tests/overview.rs +++ b/crates/ld-server/tests/overview.rs @@ -147,15 +147,16 @@ async fn decisions_one_line_per_doc_with_the_modules_left_to_vote() { assert_eq!(docs.len(), 1); assert_eq!(docs[0]["slug"], "acte-engagement-certification"); assert_eq!(docs[0]["title"]["fr"], "Acte d'engagement Certification"); - // 3 seeds a minima + 30 open articles, the two variants counting once; the title of the - // document and the order of 7 sections (« ordonnancement » holds one article: nothing to decide). + // 3 seed proposals (ADR 0011) + 30 open articles, the two variants counting once; the title + // of the document and the order of 7 sections (« ordonnancement » holds one article: nothing + // to decide). assert_eq!(docs[0]["toVote"], 41); assert_eq!(docs[0]["withoutMyVote"], 41); let doc = the_doc(&mut c, "essai").await; c.vote(&version(&doc, "E3", "0"), "for").await; c.vote(&version(&doc, "E3", "1"), "against").await; - c.vote(&version(&doc, "I1", "inForce"), "for").await; + c.vote(&version(&doc, "I1", "0"), "for").await; let d = decisions(&mut c, "essai").await; assert_eq!((d["docs"][0]["toVote"].as_u64(), d["docs"][0]["withoutMyVote"].as_u64()), (Some(41), Some(39))); // Someone else has not voted yet. diff --git a/crates/ld-server/tests/seed_proposals.rs b/crates/ld-server/tests/seed_proposals.rs index 453e5e5..a8fe523 100644 --- a/crates/ld-server/tests/seed_proposals.rs +++ b/crates/ld-server/tests/seed_proposals.rs @@ -140,7 +140,9 @@ async fn a_new_base_is_born_with_three_seed_proposals_and_no_article_in_force() assert_eq!(marked.len(), 3, "{group}"); let title = &doc["modules"]["title"]["inForce"]; assert_eq!((title["seedMinimal"].as_bool(), title["seedProposal"].as_bool()), (Some(true), Some(false))); - assert!(doc["modules"]["orders"].as_array().expect("orders").iter().all(|o| o["inForce"]["seedMinimal"] == true)); + assert!( + doc["modules"]["orders"].as_array().expect("orders").iter().all(|o| o["inForce"]["seedMinimal"] == true) + ); // The counts: no article in force, three more open versions; still 41 modules to vote. let g = c.get(&format!("/api/groups/{group}")).await; assert_eq!((g["docs"][0]["inForce"].as_u64(), g["docs"][0]["open"].as_u64()), (Some(0), Some(35)), "{group}"); @@ -203,7 +205,8 @@ const PREAMBULE: [(&str, &str, &str); 3] = [ /// The seed production runs on 2026-11-02 (3f10a0e): I1, E1 and E2 in force, seeds a /// minima, I1 and E1 at level 3 and 4. fn production_seed() -> Value { - let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/seed-production-2026-11-02/acte-engagement-certification.json"); + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures/seed-production-2026-11-02/acte-engagement-certification.json"); serde_json::from_str(&std::fs::read_to_string(path).expect("seed")).expect("json") } @@ -426,7 +429,12 @@ async fn the_production_base_turns_its_untouched_texts_into_seed_proposals_once( }; assert_eq!( changes, - [line("essai", "E1", "4"), line("essai", "E2", "4"), line("essai", "I1", "3"), line("monnaie-libre", "E2", "4")] + [ + line("essai", "E1", "4"), + line("essai", "E2", "4"), + line("essai", "I1", "3"), + line("monnaie-libre", "E2", "4") + ] ); let mut c = Client::of(&state); c.login("Chiara", false).await; diff --git a/crates/ld-server/tests/typos.rs b/crates/ld-server/tests/typos.rs index 8ba2b57..8524498 100644 --- a/crates/ld-server/tests/typos.rs +++ b/crates/ld-server/tests/typos.rs @@ -21,7 +21,8 @@ impl Client { async fn new() -> (Self, AppState) { let db = open_db("sqlite::memory:").await.expect("db"); let mut cfg = Config::for_tests(); - cfg.seed_dir = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/seed-production-2026-11-02"); + cfg.seed_dir = + std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/seed-production-2026-11-02"); let state = AppState::new(cfg, db).await.expect("state"); seed::ensure(&state).await.expect("seed"); (Self { router: app(state.clone()), cookie: None }, state)