From 0e7a34d6bf00fce0eccdf391f8d058688b911cd4 Mon Sep 17 00:00:00 2001 From: funman300 Date: Mon, 27 Apr 2026 04:54:47 +0000 Subject: [PATCH] test(server): verify merge-on-push keeps higher stats across two pushes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pushes games_played=20, then pushes games_played=5 (lower). Pulls and asserts games_played is still 20 — confirming the server merges (takes the max) rather than overwriting with the lower value. Co-Authored-By: Claude Sonnet 4.6 --- solitaire_server/tests/server_tests.rs | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/solitaire_server/tests/server_tests.rs b/solitaire_server/tests/server_tests.rs index 8c2178d..6e047e2 100644 --- a/solitaire_server/tests/server_tests.rs +++ b/solitaire_server/tests/server_tests.rs @@ -986,6 +986,50 @@ async fn opt_in_33_unicode_chars_display_name_returns_400() { ); } +/// A second push with lower stats must not overwrite the higher stored values — +/// the server merges (max wins) rather than blindly replacing. +#[tokio::test] +async fn second_push_with_lower_stats_preserves_higher_stored_values() { + set_jwt_secret(); + let app = build_test_router(test_pool().await); + + let (access, _) = register_user(app.clone(), "merge_test", "merge_pass").await; + let user_id = decode_sub(&access); + + // First push: 20 games_played. + let high_payload = make_payload(&user_id, 20); + let r1 = post_authed( + app.clone(), + "/api/sync/push", + &access, + serde_json::to_value(&high_payload).unwrap(), + ) + .await; + assert_eq!(r1.status(), StatusCode::OK); + + // Second push: 5 games_played (lower — should be ignored by merge). + let low_payload = make_payload(&user_id, 5); + let r2 = post_authed( + app.clone(), + "/api/sync/push", + &access, + serde_json::to_value(&low_payload).unwrap(), + ) + .await; + assert_eq!(r2.status(), StatusCode::OK); + + // Pull and verify the higher value survived. + let pull_resp = get_authed(app, "/api/sync/pull", &access).await; + let body = body_json(pull_resp).await; + let games_played = body["merged"]["stats"]["games_played"] + .as_u64() + .expect("games_played must be present"); + assert_eq!( + games_played, 20, + "server merge must keep the higher games_played value" + ); +} + /// Login with leading/trailing whitespace in the username still succeeds. #[tokio::test] async fn login_trims_whitespace_from_username() {