diff --git a/src/tests/account_lock.rs b/src/tests/account_lock.rs index 1c81e32eb4f..60d37b6b890 100644 --- a/src/tests/account_lock.rs +++ b/src/tests/account_lock.rs @@ -1,6 +1,7 @@ use crate::{util::RequestHelper, TestApp}; -use chrono::{Duration, NaiveDateTime, Utc}; +use chrono::{DateTime, Duration, NaiveDateTime, Utc}; use http::StatusCode; +use insta::assert_snapshot; const URL: &str = "/api/v1/me"; const LOCK_REASON: &str = "test lock reason"; @@ -28,30 +29,22 @@ async fn account_locked_indefinitely() { let response = user.get::<()>(URL).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - - let error_message = format!("This account is indefinitely locked. Reason: {LOCK_REASON}"); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": error_message }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"This account is indefinitely locked. Reason: test lock reason"}]}"#); } #[tokio::test(flavor = "multi_thread")] async fn account_locked_with_future_expiry() { - let until = Utc::now().naive_utc() + Duration::days(1); + let until = "2099-12-12T12:12:12Z" + .parse::>() + .unwrap() + .naive_utc(); let (app, _anon, user) = TestApp::init().with_user(); lock_account(&app, user.as_model().id, Some(until)); - let until = until.format("%Y-%m-%d at %H:%M:%S UTC"); let response = user.get::<()>(URL).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - - let error_message = format!("This account is locked until {until}. Reason: {LOCK_REASON}"); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": error_message }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"This account is locked until 2099-12-12 at 12:12:12 UTC. Reason: test lock reason"}]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/krate/publish/auth.rs b/src/tests/krate/publish/auth.rs index e4ae4fe5a59..f2bb9078922 100644 --- a/src/tests/krate/publish/auth.rs +++ b/src/tests/krate/publish/auth.rs @@ -4,7 +4,7 @@ use crates_io::schema::api_tokens; use diesel::{ExpressionMethods, RunQueryDsl}; use googletest::prelude::*; use http::StatusCode; -use insta::{assert_json_snapshot, assert_snapshot}; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_wrong_token() { @@ -47,7 +47,7 @@ async fn new_krate_wrong_user() { let response = another_user.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing."}]}"#); assert_that!(app.stored_files().await, empty()); assert_that!(app.emails(), empty()); diff --git a/src/tests/krate/publish/basics.rs b/src/tests/krate/publish/basics.rs index 7d305293330..87e32e766f4 100644 --- a/src/tests/krate/publish/basics.rs +++ b/src/tests/krate/publish/basics.rs @@ -125,7 +125,7 @@ async fn new_krate_duplicate_version() { let crate_to_publish = PublishBuilder::new("foo_dupe", "1.0.0"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate version `1.0.0` is already uploaded"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/categories.rs b/src/tests/krate/publish/categories.rs index 713cffe5f63..e76bedbcc95 100644 --- a/src/tests/krate/publish/categories.rs +++ b/src/tests/krate/publish/categories.rs @@ -50,6 +50,6 @@ async fn too_many_categories() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"expected at most 5 categories per crate"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/dependencies.rs b/src/tests/krate/publish/dependencies.rs index bf88c738890..a9b7eafc04f 100644 --- a/src/tests/krate/publish/dependencies.rs +++ b/src/tests/krate/publish/dependencies.rs @@ -12,7 +12,7 @@ async fn invalid_dependency_name() { .publish_crate(PublishBuilder::new("foo", "1.0.0").dependency(DependencyBuilder::new("🦀"))) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `🦀` in dependency name: `🦀`, the first character must be an ASCII character"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -50,7 +50,7 @@ async fn invalid_dependency_rename() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `💩` in dependency name: `💩`, the first character must be an ASCII character, or `_`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -70,7 +70,7 @@ async fn invalid_dependency_name_starts_with_digit() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"the name `1-foo` cannot be used as a dependency name, the name cannot start with a digit"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -90,7 +90,7 @@ async fn invalid_dependency_name_contains_unicode_chars() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `🦀` in dependency name: `foo-🦀-bar`, characters must be an ASCII alphanumeric characters, `-`, or `_`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -110,7 +110,7 @@ async fn invalid_too_long_dependency_name() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"the dependency name `fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff` is too long (max 64 characters)"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -129,7 +129,7 @@ async fn empty_dependency_name() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"dependency name cannot be empty"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -202,7 +202,7 @@ async fn new_krate_with_broken_dependency_requirement() { let crate_to_publish = PublishBuilder::new("new_dep", "1.0.0").dependency(dependency); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"\"broken\" is an invalid version requirement"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -221,7 +221,7 @@ async fn reject_new_krate_with_non_exact_dependency() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"no known crate named `foo_dep`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -249,7 +249,7 @@ async fn reject_new_crate_with_alternative_registry_dependency() { PublishBuilder::new("depends-on-alt-registry", "1.0.0").dependency(dependency); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Dependency `dep` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io."}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -268,7 +268,7 @@ async fn new_krate_with_wildcard_dependency() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r##"{"errors":[{"detail":"wildcard (`*`) dependency constraints are not allowed on crates.io. Crate with this problem: `foo_wild` See https://doc.rust-lang.org/cargo/faq.html#can-libraries-use--as-a-version-for-their-dependencies for more information"}]}"##); assert_that!(app.stored_files().await, empty()); } @@ -283,7 +283,7 @@ async fn new_krate_dependency_missing() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"no known crate named `bar_missing`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -321,7 +321,7 @@ async fn invalid_feature_name() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `🍺` in feature `🍺`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/emails.rs b/src/tests/krate/publish/emails.rs index 2b0b487db43..92b0fa65a3b 100644 --- a/src/tests/krate/publish/emails.rs +++ b/src/tests/krate/publish/emails.rs @@ -4,7 +4,7 @@ use crates_io::schema::emails; use diesel::{delete, update, ExpressionMethods, RunQueryDsl}; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_krate_without_any_email_fails() { @@ -18,7 +18,7 @@ async fn new_krate_without_any_email_fails() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"A verified email address is required to publish crates to crates.io. Visit https://crates.io/settings/profile to set and verify your email address."}]}"#); assert_that!(app.stored_files().await, empty()); assert_that!(app.emails(), empty()); } @@ -38,7 +38,7 @@ async fn new_krate_with_unverified_email_fails() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"A verified email address is required to publish crates to crates.io. Visit https://crates.io/settings/profile to set and verify your email address."}]}"#); assert_that!(app.stored_files().await, empty()); assert_that!(app.emails(), empty()); } diff --git a/src/tests/krate/publish/features.rs b/src/tests/krate/publish/features.rs index b04b59e9a7c..26f7f17f393 100644 --- a/src/tests/krate/publish/features.rs +++ b/src/tests/krate/publish/features.rs @@ -2,7 +2,7 @@ use crate::builders::{CrateBuilder, DependencyBuilder, PublishBuilder}; use crate::util::{RequestHelper, TestApp}; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::{assert_json_snapshot, assert_snapshot}; #[tokio::test(flavor = "multi_thread")] async fn features_version_2() { @@ -60,7 +60,7 @@ async fn empty_feature_name() { let crate_to_publish = PublishBuilder::new("foo", "1.0.0").feature("", &[]); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"feature cannot be empty"}]}"#); assert!(app.stored_files().await.is_empty()); } @@ -71,7 +71,7 @@ async fn invalid_feature_name1() { let crate_to_publish = PublishBuilder::new("foo", "1.0.0").feature("~foo", &[]); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `~` in feature `~foo`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -82,7 +82,7 @@ async fn invalid_feature_name2() { let crate_to_publish = PublishBuilder::new("foo", "1.0.0").feature("foo", &["!bar"]); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `!` in feature `!bar`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -92,7 +92,7 @@ async fn invalid_feature_name_start_with_hyphen() { let crate_to_publish = PublishBuilder::new("foo", "1.0.0").feature("-foo1.bar", &[]); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid character `-` in feature `-foo1.bar`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)"}]}"#); assert!(app.stored_files().await.is_empty()); } @@ -112,7 +112,7 @@ async fn too_many_features() { .feature("five", &[]); let response = token.publish_crate(publish_builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crates.io only allows a maximum number of 3 features, but your crate is declaring 5 features.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details."}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -138,7 +138,7 @@ async fn too_many_features_with_custom_limit() { .feature("five", &[]); let response = token.publish_crate(publish_builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crates.io only allows a maximum number of 4 features, but your crate is declaring 5 features.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details."}]}"#); assert_that!(app.stored_files().await, empty()); let publish_builder = PublishBuilder::new("foo", "1.0.0") @@ -169,7 +169,7 @@ async fn too_many_enabled_features() { .feature("default", &["one", "two", "three", "four", "five"]); let response = token.publish_crate(publish_builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crates.io only allows a maximum number of 3 features or dependencies that another feature can enable, but the \"default\" feature of your crate is enabling 5 features or dependencies.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details."}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -191,7 +191,7 @@ async fn too_many_enabled_features_with_custom_limit() { .feature("default", &["one", "two", "three", "four", "five"]); let response = token.publish_crate(publish_builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crates.io only allows a maximum number of 4 features or dependencies that another feature can enable, but the \"default\" feature of your crate is enabling 5 features or dependencies.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details."}]}"#); assert_that!(app.stored_files().await, empty()); let publish_builder = diff --git a/src/tests/krate/publish/inheritance.rs b/src/tests/krate/publish/inheritance.rs index 3c014f4093e..69b49bff6e0 100644 --- a/src/tests/krate/publish/inheritance.rs +++ b/src/tests/krate/publish/inheritance.rs @@ -1,7 +1,7 @@ use crate::builders::PublishBuilder; use crate::util::{RequestHelper, TestApp}; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn workspace_inheritance() { @@ -14,7 +14,7 @@ async fn workspace_inheritance() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\nvalue from workspace hasn't been set"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -25,5 +25,5 @@ async fn workspace_inheritance_with_dep() { "[package]\nname = \"foo\"\nversion = \"1.0.0\"\n\n[dependencies]\nserde.workspace = true\n", )).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\nvalue from workspace hasn't been set"}]}"#); } diff --git a/src/tests/krate/publish/keywords.rs b/src/tests/krate/publish/keywords.rs index 85daacfcc74..069d803f0c4 100644 --- a/src/tests/krate/publish/keywords.rs +++ b/src/tests/krate/publish/keywords.rs @@ -2,7 +2,7 @@ use crate::builders::PublishBuilder; use crate::util::{RequestHelper, TestApp}; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::{assert_json_snapshot, assert_snapshot}; #[tokio::test(flavor = "multi_thread")] async fn good_keywords() { @@ -26,17 +26,17 @@ async fn bad_keywords() { PublishBuilder::new("foo_bad_key", "1.0.0").keyword("super-long-keyword-name-oh-no"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"\"super-long-keyword-name-oh-no\" is an invalid keyword (keywords must have less than 20 characters)"}]}"#); let crate_to_publish = PublishBuilder::new("foo_bad_key", "1.0.0").keyword("?@?%"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"\"?@?%\" is an invalid keyword"}]}"#); let crate_to_publish = PublishBuilder::new("foo_bad_key", "1.0.0").keyword("áccênts"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"\"áccênts\" is an invalid keyword"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -54,6 +54,6 @@ async fn too_many_keywords() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"expected at most 5 keywords per crate"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/manifest.rs b/src/tests/krate/publish/manifest.rs index fe3b6223e7c..9a1c402aa81 100644 --- a/src/tests/krate/publish/manifest.rs +++ b/src/tests/krate/publish/manifest.rs @@ -2,7 +2,7 @@ use crate::builders::PublishBuilder; use crate::util::insta::{any_id_redaction, id_redaction}; use crate::util::{RequestHelper, TestApp}; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::{assert_json_snapshot, assert_snapshot}; #[tokio::test(flavor = "multi_thread")] async fn boolean_readme() { @@ -47,7 +47,7 @@ async fn missing_manifest() { .publish_crate(PublishBuilder::new("foo", "1.0.0").no_manifest()) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"uploaded tarball is missing a `Cargo.toml` manifest file"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -65,7 +65,7 @@ async fn manifest_casing() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"uploaded tarball is missing a `Cargo.toml` manifest file; `CARGO.TOML` was found, but must be named `Cargo.toml` with that exact casing"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -87,7 +87,7 @@ async fn multiple_manifests() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"uploaded tarball contains more than one `Cargo.toml` manifest file; found `Cargo.toml`, `cargo.toml`"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -98,7 +98,7 @@ async fn invalid_manifest() { .publish_crate(PublishBuilder::new("foo", "1.0.0").custom_manifest("")) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\nmissing field `name`\n"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -111,7 +111,7 @@ async fn invalid_manifest_missing_name() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\nTOML parse error at line 1, column 1\n |\n1 | [package]\n | ^^^^^^^^^\nmissing field `name`\n"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -124,7 +124,7 @@ async fn invalid_manifest_missing_version() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\nmissing field `version`"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -136,13 +136,13 @@ async fn invalid_rust_version() { "[package]\nname = \"foo\"\nversion = \"1.0.0\"\ndescription = \"description\"\nlicense = \"MIT\"\nrust-version = \"\"\n", )).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\ninvalid `rust-version` value"}]}"#); let response = token.publish_crate(PublishBuilder::new("foo", "1.0.0").custom_manifest( "[package]\nname = \"foo\"\nversion = \"1.0.0\"\ndescription = \"description\"\nlicense = \"MIT\"\nrust-version = \"1.0.0-beta.2\"\n", )).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"failed to parse `Cargo.toml` manifest file\n\ninvalid `rust-version` value"}]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/krate/publish/max_size.rs b/src/tests/krate/publish/max_size.rs index 583600460dd..60d4cd7cfab 100644 --- a/src/tests/krate/publish/max_size.rs +++ b/src/tests/krate/publish/max_size.rs @@ -89,7 +89,7 @@ async fn tarball_bigger_than_max_upload_size() { let response = token.publish_crate(body).await; assert_eq!(response.status(), StatusCode::PAYLOAD_TOO_LARGE); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"max upload size is: 5242880"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -107,8 +107,7 @@ async fn new_krate_gzip_bomb() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"uploaded tarball is malformed or too large when decompressed"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -126,8 +125,7 @@ async fn new_krate_too_big() { let response = user.publish_crate(builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"uploaded tarball is malformed or too large when decompressed"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/similar_names.rs b/src/tests/krate/publish/similar_names.rs index 0abb24c72d8..db1e5b7ca1f 100644 --- a/src/tests/krate/publish/similar_names.rs +++ b/src/tests/krate/publish/similar_names.rs @@ -2,7 +2,7 @@ use crate::builders::{CrateBuilder, PublishBuilder}; use crate::util::{RequestHelper, TestApp}; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_crate_similar_name() { @@ -17,8 +17,7 @@ async fn new_crate_similar_name() { let crate_to_publish = PublishBuilder::new("foo_similar", "1.1.0"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate was previously named `Foo_similar`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -35,8 +34,7 @@ async fn new_crate_similar_name_hyphen() { let crate_to_publish = PublishBuilder::new("foo-bar-hyphen", "1.1.0"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate was previously named `foo_bar_hyphen`"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -53,7 +51,6 @@ async fn new_crate_similar_name_underscore() { let crate_to_publish = PublishBuilder::new("foo_bar_underscore", "1.1.0"); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate was previously named `foo-bar-underscore`"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__auth__new_krate_wrong_user.snap b/src/tests/krate/publish/snapshots/all__krate__publish__auth__new_krate_wrong_user.snap deleted file mode 100644 index 907bd2c351b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__auth__new_krate_wrong_user.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/auth.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__basics__new_krate_duplicate_version.snap b/src/tests/krate/publish/snapshots/all__krate__publish__basics__new_krate_duplicate_version.snap deleted file mode 100644 index 139188138e3..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__basics__new_krate_duplicate_version.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/basics.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crate version `1.0.0` is already uploaded" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__categories__too_many_categories.snap b/src/tests/krate/publish/snapshots/all__krate__publish__categories__too_many_categories.snap deleted file mode 100644 index 5970faae56c..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__categories__too_many_categories.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/categories.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "expected at most 5 categories per crate" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__empty_dependency_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__empty_dependency_name.snap deleted file mode 100644 index a7cdb7a7aee..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__empty_dependency_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "dependency name cannot be empty" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name.snap deleted file mode 100644 index e9ada2bf9ac..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `🦀` in dependency name: `🦀`, the first character must be an ASCII character" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_contains_unicode_chars.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_contains_unicode_chars.snap deleted file mode 100644 index 67e0410c3ef..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_contains_unicode_chars.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `🦀` in dependency name: `foo-🦀-bar`, characters must be an ASCII alphanumeric characters, `-`, or `_`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_starts_with_digit.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_starts_with_digit.snap deleted file mode 100644 index 7d08f394b5d..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_name_starts_with_digit.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "the name `1-foo` cannot be used as a dependency name, the name cannot start with a digit" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_rename.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_rename.snap deleted file mode 100644 index d4d08413d9e..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_dependency_rename.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `💩` in dependency name: `💩`, the first character must be an ASCII character, or `_`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_feature_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_feature_name.snap deleted file mode 100644 index f9566fa6ba2..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_feature_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `🍺` in feature `🍺`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_too_long_dependency_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_too_long_dependency_name.snap deleted file mode 100644 index a5c7e31b823..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__invalid_too_long_dependency_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "the dependency name `fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff` is too long (max 64 characters)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_dependency_missing.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_dependency_missing.snap deleted file mode 100644 index 4bf84939b3e..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_dependency_missing.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "no known crate named `bar_missing`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_broken_dependency_requirement.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_broken_dependency_requirement.snap deleted file mode 100644 index d7ab80bfdf5..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_broken_dependency_requirement.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "\"broken\" is an invalid version requirement" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_wildcard_dependency.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_wildcard_dependency.snap deleted file mode 100644 index bd0d135e545..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__new_krate_with_wildcard_dependency.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "wildcard (`*`) dependency constraints are not allowed on crates.io. Crate with this problem: `foo_wild` See https://doc.rust-lang.org/cargo/faq.html#can-libraries-use--as-a-version-for-their-dependencies for more information" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_crate_with_alternative_registry_dependency.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_crate_with_alternative_registry_dependency.snap deleted file mode 100644 index d87c24ac50c..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_crate_with_alternative_registry_dependency.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "Dependency `dep` is hosted on another registry. Cross-registry dependencies are not permitted on crates.io." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_krate_with_non_exact_dependency.snap b/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_krate_with_non_exact_dependency.snap deleted file mode 100644 index a22fcd2f65b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__dependencies__reject_new_krate_with_non_exact_dependency.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/dependencies.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "no known crate named `foo_dep`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_with_unverified_email_fails.snap b/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_with_unverified_email_fails.snap deleted file mode 100644 index e324e6bc97b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_with_unverified_email_fails.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/emails.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "A verified email address is required to publish crates to crates.io. Visit https://crates.io/settings/profile to set and verify your email address." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_without_any_email_fails.snap b/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_without_any_email_fails.snap deleted file mode 100644 index e324e6bc97b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__emails__new_krate_without_any_email_fails.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/emails.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "A verified email address is required to publish crates to crates.io. Visit https://crates.io/settings/profile to set and verify your email address." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__empty_feature_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__empty_feature_name.snap deleted file mode 100644 index 63b2f9fd1de..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__empty_feature_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "feature cannot be empty" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name1.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name1.snap deleted file mode 100644 index 3df54b3eb26..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name1.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `~` in feature `~foo`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name2.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name2.snap deleted file mode 100644 index 8d5ba6c9916..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name2.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `!` in feature `!bar`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name_start_with_hyphen.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name_start_with_hyphen.snap deleted file mode 100644 index 28d85852bd3..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__invalid_feature_name_start_with_hyphen.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid character `-` in feature `-foo1.bar`, the first character must be a Unicode XID start character or digit (most letters or `_` or `0` to `9`)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features.snap deleted file mode 100644 index 3e8154c9e85..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crates.io only allows a maximum number of 3 features or dependencies that another feature can enable, but the \"default\" feature of your crate is enabling 5 features or dependencies.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features_with_custom_limit.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features_with_custom_limit.snap deleted file mode 100644 index 3ad9ddccffe..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_enabled_features_with_custom_limit.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crates.io only allows a maximum number of 4 features or dependencies that another feature can enable, but the \"default\" feature of your crate is enabling 5 features or dependencies.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features.snap deleted file mode 100644 index ebcd99ea41a..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crates.io only allows a maximum number of 3 features, but your crate is declaring 5 features.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features_with_custom_limit.snap b/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features_with_custom_limit.snap deleted file mode 100644 index 612abdad24a..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__features__too_many_features_with_custom_limit.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/features.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crates.io only allows a maximum number of 4 features, but your crate is declaring 5 features.\n\nTake a look at https://blog.rust-lang.org/2023/10/26/broken-badges-and-23k-keywords.html to understand why this restriction was introduced.\n\nIf you have a use case that requires an increase of this limit, please send us an email to help@crates.io to discuss the details." - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance.snap b/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance.snap deleted file mode 100644 index 508efee5a9a..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/inheritance.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\nvalue from workspace hasn't been set" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance_with_dep.snap b/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance_with_dep.snap deleted file mode 100644 index 508efee5a9a..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__inheritance__workspace_inheritance_with_dep.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/inheritance.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\nvalue from workspace hasn't been set" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-2.snap b/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-2.snap deleted file mode 100644 index 31a5e5376b7..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-2.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/keywords.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "\"?@?%\" is an invalid keyword" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-3.snap b/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-3.snap deleted file mode 100644 index d8f0da91108..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords-3.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/keywords.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "\"áccênts\" is an invalid keyword" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords.snap b/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords.snap deleted file mode 100644 index 39a2408a37c..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__bad_keywords.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/keywords.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "\"super-long-keyword-name-oh-no\" is an invalid keyword (keywords must have less than 20 characters)" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__too_many_keywords.snap b/src/tests/krate/publish/snapshots/all__krate__publish__keywords__too_many_keywords.snap deleted file mode 100644 index c06d34e03bf..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__keywords__too_many_keywords.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/keywords.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "expected at most 5 keywords per crate" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest.snap deleted file mode 100644 index 5ecfc697d05..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\nmissing field `name`\n" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_name.snap deleted file mode 100644 index 3a0917cc2e2..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\nTOML parse error at line 1, column 1\n |\n1 | [package]\n | ^^^^^^^^^\nmissing field `name`\n" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_version.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_version.snap deleted file mode 100644 index 0ab04137d42..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_manifest_missing_version.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\nmissing field `version`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version-2.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version-2.snap deleted file mode 100644 index 9b4cc2e109b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version-2.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\ninvalid `rust-version` value" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version.snap deleted file mode 100644 index 9b4cc2e109b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__invalid_rust_version.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "failed to parse `Cargo.toml` manifest file\n\ninvalid `rust-version` value" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__manifest_casing.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__manifest_casing.snap deleted file mode 100644 index f44140d185d..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__manifest_casing.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "uploaded tarball is missing a `Cargo.toml` manifest file; `CARGO.TOML` was found, but must be named `Cargo.toml` with that exact casing" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__missing_manifest.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__missing_manifest.snap deleted file mode 100644 index 20a899011d5..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__missing_manifest.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "uploaded tarball is missing a `Cargo.toml` manifest file" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__multiple_manifests.snap b/src/tests/krate/publish/snapshots/all__krate__publish__manifest__multiple_manifests.snap deleted file mode 100644 index 03ac9313687..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__manifest__multiple_manifests.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/manifest.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "uploaded tarball contains more than one `Cargo.toml` manifest file; found `Cargo.toml`, `cargo.toml`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_gzip_bomb.snap b/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_gzip_bomb.snap deleted file mode 100644 index 6fd4126bb40..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_gzip_bomb.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/max_size.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "uploaded tarball is malformed or too large when decompressed" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_too_big.snap b/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_too_big.snap deleted file mode 100644 index 6fd4126bb40..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__new_krate_too_big.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/max_size.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "uploaded tarball is malformed or too large when decompressed" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__tarball_bigger_than_max_upload_size.snap b/src/tests/krate/publish/snapshots/all__krate__publish__max_size__tarball_bigger_than_max_upload_size.snap deleted file mode 100644 index d98bb096f2a..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__max_size__tarball_bigger_than_max_upload_size.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/max_size.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "max upload size is: 5242880" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name.snap b/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name.snap deleted file mode 100644 index f42f69e360b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/similar_names.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crate was previously named `Foo_similar`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_hyphen.snap b/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_hyphen.snap deleted file mode 100644 index d108dd798bc..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_hyphen.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/similar_names.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crate was previously named `foo_bar_hyphen`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_underscore.snap b/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_underscore.snap deleted file mode 100644 index 8f1255421cd..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__similar_names__new_crate_similar_name_underscore.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/similar_names.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "crate was previously named `foo-bar-underscore`" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__empty_body.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__empty_body.snap deleted file mode 100644 index 88c5004dd4d..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__empty_body.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid metadata length" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_bytes_truncated.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_bytes_truncated.snap deleted file mode 100644 index 3bdeedb9821..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_bytes_truncated.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid metadata length for remaining payload: 100" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_len_truncated.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_len_truncated.snap deleted file mode 100644 index 88c5004dd4d..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__json_len_truncated.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid metadata length" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__new_krate_tarball_with_hard_links.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__new_krate_tarball_with_hard_links.snap deleted file mode 100644 index 4239ad020dc..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__new_krate_tarball_with_hard_links.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "unexpected symlink or hard link found: foo-1.1.0/bar" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_bytes_truncated.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_bytes_truncated.snap deleted file mode 100644 index 28da20a7a29..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_bytes_truncated.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid tarball length for remaining payload: 100" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_len_truncated.snap b/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_len_truncated.snap deleted file mode 100644 index e61731464a4..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__tarball__tarball_len_truncated.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/tarball.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid tarball length" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__empty_json.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__empty_json.snap deleted file mode 100644 index bdff0a0b343..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__empty_json.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid upload request: missing field `name` at line 1 column 2" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_license.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_license.snap deleted file mode 100644 index 4e629fbe94c..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_license.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "unknown or invalid license expression; see http://opensource.org/licenses for options, and http://spdx.org/licenses/ for their identifiers\nNote: If you have a non-standard license that is not listed by SPDX, use the license-file field to specify the path to a file containing the text of the license.\nSee https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information.\nMIT AND foobar\n ^^^^^^ unknown term" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_urls.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_urls.snap deleted file mode 100644 index e8b7a24183e..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_urls.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "URL for field `documentation` must begin with http:// or https:// (url: javascript:alert('boom'))" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_version.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_version.snap deleted file mode 100644 index 66700b630a5..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__invalid_version.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "\"broken\" is an invalid semver version" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-2.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-2.snap deleted file mode 100644 index b736fc7cb57..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-2.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "missing or empty metadata fields: description. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-3.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-3.snap deleted file mode 100644 index b736fc7cb57..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required-3.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "missing or empty metadata fields: description. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields" - } - ] -} diff --git a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required.snap b/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required.snap deleted file mode 100644 index 5a903c9e27b..00000000000 --- a/src/tests/krate/publish/snapshots/all__krate__publish__validation__license_and_description_required.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/krate/publish/validation.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields" - } - ] -} diff --git a/src/tests/krate/publish/tarball.rs b/src/tests/krate/publish/tarball.rs index ffdf894a614..3a523d195ca 100644 --- a/src/tests/krate/publish/tarball.rs +++ b/src/tests/krate/publish/tarball.rs @@ -3,7 +3,7 @@ use crate::util::{RequestHelper, TestApp}; use crates_io_tarball::TarballBuilder; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn new_krate_wrong_files() { @@ -15,11 +15,7 @@ async fn new_krate_wrong_files() { let response = user.publish_crate(builder).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid path found: bar-1.0.0/a" }] }) - ); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid path found: bar-1.0.0/a"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -46,7 +42,7 @@ async fn new_krate_tarball_with_hard_links() { let response = token.publish_crate(body).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"unexpected symlink or hard link found: foo-1.1.0/bar"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -56,7 +52,7 @@ async fn empty_body() { let response = user.publish_crate(&[] as &[u8]).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid metadata length"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -66,7 +62,7 @@ async fn json_len_truncated() { let response = token.publish_crate(&[0u8, 0] as &[u8]).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid metadata length"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -76,7 +72,7 @@ async fn json_bytes_truncated() { let response = token.publish_crate(&[100u8, 0, 0, 0, 0] as &[u8]).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid metadata length for remaining payload: 100"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -88,7 +84,7 @@ async fn tarball_len_truncated() { .publish_crate(&[2, 0, 0, 0, b'{', b'}', 0, 0] as &[u8]) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid tarball length"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -100,6 +96,6 @@ async fn tarball_bytes_truncated() { .publish_crate(&[2, 0, 0, 0, b'{', b'}', 100, 0, 0, 0, 0] as &[u8]) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid tarball length for remaining payload: 100"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/krate/publish/validation.rs b/src/tests/krate/publish/validation.rs index b3ddac33193..36ef5811c85 100644 --- a/src/tests/krate/publish/validation.rs +++ b/src/tests/krate/publish/validation.rs @@ -14,7 +14,7 @@ async fn empty_json() { let response = token.publish_crate(body).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid upload request: missing field `name` at line 1 column 2"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -55,7 +55,7 @@ async fn invalid_version() { let response = token.publish_crate(body).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"\"broken\" is an invalid semver version"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -69,14 +69,12 @@ async fn license_and_description_required() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields"}]}"#); let crate_to_publish = PublishBuilder::new("foo_metadata", "1.1.0").unset_description(); let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"missing or empty metadata fields: description. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields"}]}"#); let crate_to_publish = PublishBuilder::new("foo_metadata", "1.1.0") .unset_license() .license_file("foo") @@ -84,8 +82,7 @@ async fn license_and_description_required() { let response = token.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"missing or empty metadata fields: description. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields"}]}"#); assert_that!(app.stored_files().await, empty()); } @@ -111,7 +108,7 @@ async fn invalid_license() { .publish_crate(PublishBuilder::new("foo", "1.0.0").license("MIT AND foobar")) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r##"{"errors":[{"detail":"unknown or invalid license expression; see http://opensource.org/licenses for options, and http://spdx.org/licenses/ for their identifiers\nNote: If you have a non-standard license that is not listed by SPDX, use the license-file field to specify the path to a file containing the text of the license.\nSee https://doc.rust-lang.org/cargo/reference/manifest.html#the-license-and-license-file-fields for more information.\nMIT AND foobar\n ^^^^^^ unknown term"}]}"##); assert_that!(app.stored_files().await, empty()); } @@ -125,7 +122,6 @@ async fn invalid_urls() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); - + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"URL for field `documentation` must begin with http:// or https:// (url: javascript:alert('boom'))"}]}"#); assert_that!(app.stored_files().await, empty()); } diff --git a/src/tests/not_found_error.rs b/src/tests/not_found_error.rs index 106129fe023..0fa06ec7eef 100644 --- a/src/tests/not_found_error.rs +++ b/src/tests/not_found_error.rs @@ -1,5 +1,6 @@ use crate::{RequestHelper, TestApp}; use http::StatusCode; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn visiting_unknown_route_returns_404() { @@ -7,10 +8,7 @@ async fn visiting_unknown_route_returns_404() { let response = anon.get::<()>("/does-not-exist").await; assert_eq!(response.status(), StatusCode::NOT_FOUND); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "Not Found" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Not Found"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -19,8 +17,5 @@ async fn visiting_unknown_api_route_returns_404() { let response = anon.get::<()>("/api/v1/does-not-exist").await; assert_eq!(response.status(), StatusCode::NOT_FOUND); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "Not Found" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Not Found"}]}"#); } diff --git a/src/tests/owners.rs b/src/tests/owners.rs index ba9bd6eb4a9..481df3bacce 100644 --- a/src/tests/owners.rs +++ b/src/tests/owners.rs @@ -188,10 +188,7 @@ async fn owners_can_remove_self() { .remove_named_owner("owners_selfremove", username) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required."}]}"#); create_and_add_owner(&app, &token, "secondowner", &krate).await; @@ -200,20 +197,14 @@ async fn owners_can_remove_self() { .remove_named_owner("owners_selfremove", username) .await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "msg": "owners successfully removed", "ok": true }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"owners successfully removed","ok":true}"#); // After you delete yourself, you no longer have permissions to manage the crate. let response = token .remove_named_owner("owners_selfremove", username) .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "only owners have permission to modify owners" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"only owners have permission to modify owners"}]}"#); } /// Verify consistency when adidng or removing multiple owners in a single request. @@ -235,10 +226,7 @@ async fn modify_multiple_owners() { .remove_named_owners("owners_multiple", &[username, "user2", "user3"]) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required."}]}"#); assert_eq!(app.db(|conn| krate.owners(conn).unwrap()).len(), 3); // Deleting two owners at once is allowed. @@ -246,10 +234,7 @@ async fn modify_multiple_owners() { .remove_named_owners("owners_multiple", &["user2", "user3"]) .await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "msg": "owners successfully removed", "ok": true }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"owners successfully removed","ok":true}"#); assert_eq!(app.db(|conn| krate.owners(conn).unwrap()).len(), 1); // Adding multiple users fails if one of them already is an owner. @@ -257,10 +242,7 @@ async fn modify_multiple_owners() { .add_named_owners("owners_multiple", &["user2", username]) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "`foo` is already an owner" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"`foo` is already an owner"}]}"#); assert_eq!(app.db(|conn| krate.owners(conn).unwrap()).len(), 1); // Adding multiple users at once succeeds. @@ -268,13 +250,7 @@ async fn modify_multiple_owners() { .add_named_owners("owners_multiple", &["user2", "user3"]) .await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ - "msg": "user user2 has been invited to be an owner of crate owners_multiple,user user3 has been invited to be an owner of crate owners_multiple", - "ok": true, - }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user user2 has been invited to be an owner of crate owners_multiple,user user3 has been invited to be an owner of crate owners_multiple","ok":true}"#); assert_snapshot!(app.emails_snapshot()); diff --git a/src/tests/pagination.rs b/src/tests/pagination.rs index daac14f1003..add85d7c9f9 100644 --- a/src/tests/pagination.rs +++ b/src/tests/pagination.rs @@ -1,8 +1,8 @@ use crate::builders::CrateBuilder; use crate::util::{RequestHelper, TestApp}; use http::status::StatusCode; +use insta::assert_snapshot; use ipnetwork::IpNetwork; -use serde_json::json; #[tokio::test(flavor = "multi_thread")] async fn pagination_blocks_ip_from_cidr_block_list() { @@ -24,8 +24,5 @@ async fn pagination_blocks_ip_from_cidr_block_list() { .get_with_query::<()>("/api/v1/crates", "page=2&per_page=1") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "Page 2 is unavailable for performance reasons. Please take a look at https://crates.io/data-access for alternatives." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Page 2 is unavailable for performance reasons. Please take a look at https://crates.io/data-access for alternatives."}]}"#); } diff --git a/src/tests/routes/crates/list.rs b/src/tests/routes/crates/list.rs index 05744375ad0..9f5e6bac9d8 100644 --- a/src/tests/routes/crates/list.rs +++ b/src/tests/routes/crates/list.rs @@ -6,7 +6,7 @@ use crates_io::schema::crates; use diesel::{dsl::*, prelude::*, update}; use googletest::prelude::*; use http::StatusCode; -use insta::assert_json_snapshot; +use insta::{assert_json_snapshot, assert_snapshot}; use regex::Regex; use std::sync::LazyLock; @@ -1027,7 +1027,7 @@ async fn invalid_seek_parameter() { let response = anon.get::<()>("/api/v1/crates?seek=broken").await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid seek parameter"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -1045,19 +1045,13 @@ async fn pagination_parameters_only_accept_integers() { .get_with_query::<()>("/api/v1/crates", "page=1&per_page=100%22%EF%BC%8Cexception") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid digit found in string" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid digit found in string"}]}"#); let response = anon .get_with_query::<()>("/api/v1/crates", "page=100%22%EF%BC%8Cexception&per_page=1") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid digit found in string" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid digit found in string"}]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/routes/crates/new.rs b/src/tests/routes/crates/new.rs index 5953e27c6a7..5d46834ce00 100644 --- a/src/tests/routes/crates/new.rs +++ b/src/tests/routes/crates/new.rs @@ -1,6 +1,7 @@ use crate::builders::PublishBuilder; use crate::util::{RequestHelper, TestApp}; use http::StatusCode; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn daily_limit() { @@ -15,9 +16,5 @@ async fn daily_limit() { let crate_to_publish = PublishBuilder::new("foo_daily_limit", "1.0.0"); let response = user.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::TOO_MANY_REQUESTS); - let json = response.json(); - assert_eq!( - json["errors"][0]["detail"], - "You have published too many versions of this crate in the last 24 hours" - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"You have published too many versions of this crate in the last 24 hours"}]}"#); } diff --git a/src/tests/routes/crates/owners/add.rs b/src/tests/routes/crates/owners/add.rs index 84b903956a4..95717276efa 100644 --- a/src/tests/routes/crates/owners/add.rs +++ b/src/tests/routes/crates/owners/add.rs @@ -63,10 +63,7 @@ async fn owner_change_via_cookie() { let body = serde_json::to_vec(&body).unwrap(); let response = cookie.put::<()>(&url, body).await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "ok": true, "msg": "user user-2 has been invited to be an owner of crate foo_crate" }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user user-2 has been invited to be an owner of crate foo_crate","ok":true}"#); } #[tokio::test(flavor = "multi_thread")] @@ -84,10 +81,7 @@ async fn owner_change_via_token() { let body = serde_json::to_vec(&body).unwrap(); let response = token.put::<()>(&url, body).await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "ok": true, "msg": "user user-2 has been invited to be an owner of crate foo_crate" }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user user-2 has been invited to be an owner of crate foo_crate","ok":true}"#); } #[tokio::test(flavor = "multi_thread")] @@ -106,10 +100,7 @@ async fn owner_change_via_change_owner_token() { let body = serde_json::to_vec(&body).unwrap(); let response = token.put::<()>(&url, body).await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "ok": true, "msg": "user user-2 has been invited to be an owner of crate foo_crate" }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user user-2 has been invited to be an owner of crate foo_crate","ok":true}"#); } #[tokio::test(flavor = "multi_thread")] @@ -129,10 +120,7 @@ async fn owner_change_via_change_owner_token_with_matching_crate_scope() { let body = serde_json::to_vec(&body).unwrap(); let response = token.put::<()>(&url, body).await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ "ok": true, "msg": "user user-2 has been invited to be an owner of crate foo_crate" }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user user-2 has been invited to be an owner of crate foo_crate","ok":true}"#); } #[tokio::test(flavor = "multi_thread")] @@ -249,13 +237,7 @@ async fn invite_already_invited_user() { // Invite the user the first time let response = owner.add_named_owner("crate_name", "invited_user").await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ - "msg": "user invited_user has been invited to be an owner of crate crate_name", - "ok": true, - }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user invited_user has been invited to be an owner of crate crate_name","ok":true}"#); // Check one email was sent, this will be the ownership invite email assert_eq!(app.emails().len(), 1); @@ -263,13 +245,7 @@ async fn invite_already_invited_user() { // Then invite the user a second time, the message should point out the user is already invited let response = owner.add_named_owner("crate_name", "invited_user").await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ - "msg": "user invited_user already has a pending invitation to be an owner of crate crate_name", - "ok": true, - }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user invited_user already has a pending invitation to be an owner of crate crate_name","ok":true}"#); // Check that no new email is sent after the second invitation assert_eq!(app.emails().len(), 1); @@ -288,13 +264,7 @@ async fn invite_with_existing_expired_invite() { // Invite the user the first time let response = owner.add_named_owner("crate_name", "invited_user").await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ - "msg": "user invited_user has been invited to be an owner of crate crate_name", - "ok": true, - }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user invited_user has been invited to be an owner of crate crate_name","ok":true}"#); // Check one email was sent, this will be the ownership invite email assert_eq!(app.emails().len(), 1); @@ -305,13 +275,7 @@ async fn invite_with_existing_expired_invite() { // Then invite the user a second time, a new invite is created as the old one expired let response = owner.add_named_owner("crate_name", "invited_user").await; assert_eq!(response.status(), StatusCode::OK); - assert_eq!( - response.json(), - json!({ - "msg": "user invited_user has been invited to be an owner of crate crate_name", - "ok": true, - }) - ); + assert_snapshot!(response.text(), @r#"{"msg":"user invited_user has been invited to be an owner of crate crate_name","ok":true}"#); // Check that the email for the second invite was sent assert_eq!(app.emails().len(), 2); diff --git a/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap b/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap deleted file mode 100644 index 82149660a6a..00000000000 --- a/src/tests/routes/crates/snapshots/all__routes__crates__list__invalid_seek_parameter.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/routes/crates/list.rs -expression: response.into_json() ---- -{ - "errors": [ - { - "detail": "invalid seek parameter" - } - ] -} diff --git a/src/tests/routes/crates/versions/dependencies.rs b/src/tests/routes/crates/versions/dependencies.rs index d9e3c26ee45..4d6d02c18af 100644 --- a/src/tests/routes/crates/versions/dependencies.rs +++ b/src/tests/routes/crates/versions/dependencies.rs @@ -2,6 +2,7 @@ use crate::builders::{CrateBuilder, VersionBuilder}; use crate::util::{RequestHelper, TestApp}; use crates_io::views::EncodableDependency; use http::StatusCode; +use insta::assert_snapshot; #[derive(Deserialize)] pub struct Deps { @@ -31,17 +32,11 @@ async fn dependencies() { .get::<()>("/api/v1/crates/missing-crate/1.0.0/dependencies") .await; assert_eq!(response.status(), StatusCode::NOT_FOUND); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "crate `missing-crate` does not exist" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate `missing-crate` does not exist"}]}"#); let response = anon .get::<()>("/api/v1/crates/foo_deps/1.0.2/dependencies") .await; assert_eq!(response.status(), StatusCode::NOT_FOUND); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "crate `foo_deps` does not have a version `1.0.2`" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"crate `foo_deps` does not have a version `1.0.2`"}]}"#); } diff --git a/src/tests/routes/crates/versions/list.rs b/src/tests/routes/crates/versions/list.rs index 6a34a3a8c16..e7ff6781bcb 100644 --- a/src/tests/routes/crates/versions/list.rs +++ b/src/tests/routes/crates/versions/list.rs @@ -212,14 +212,14 @@ async fn invalid_seek_parameter() { .get_with_query::<()>(url, "per_page=1&sort=semver&seek=broken") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid seek parameter"}]}"#); // Sort by date let response = anon .get_with_query::<()>(url, "per_page=1&sort=date&seek=broken") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_json_snapshot!(response.json()); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid seek parameter"}]}"#); // broken seek but without per_page parameter should be ok // since it's not consider as seek-based pagination diff --git a/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter-2.snap b/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter-2.snap deleted file mode 100644 index af305897312..00000000000 --- a/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter-2.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/routes/crates/versions/list.rs -expression: response.json() ---- -{ - "errors": [ - { - "detail": "invalid seek parameter" - } - ] -} diff --git a/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter.snap b/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter.snap deleted file mode 100644 index af305897312..00000000000 --- a/src/tests/routes/crates/versions/snapshots/all__routes__crates__versions__list__invalid_seek_parameter.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: src/tests/routes/crates/versions/list.rs -expression: response.json() ---- -{ - "errors": [ - { - "detail": "invalid seek parameter" - } - ] -} diff --git a/src/tests/routes/crates/versions/yank_unyank.rs b/src/tests/routes/crates/versions/yank_unyank.rs index 451c4bb8adf..9057103ce0e 100644 --- a/src/tests/routes/crates/versions/yank_unyank.rs +++ b/src/tests/routes/crates/versions/yank_unyank.rs @@ -2,6 +2,7 @@ use crate::builders::{CrateBuilder, PublishBuilder}; use crate::util::{RequestHelper, Response, TestApp}; use crate::OkBool; use http::StatusCode; +use insta::assert_snapshot; pub trait YankRequestHelper { /// Yank the specified version of the specified crate and run all pending background jobs @@ -41,10 +42,7 @@ async fn yank_by_a_non_owner_fails() { let response = token.yank("foo_not", "1.0.0").await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "must already be an owner to yank or unyank" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"must already be an owner to yank or unyank"}]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/routes/me/tokens/create.rs b/src/tests/routes/me/tokens/create.rs index 76548775681..1c4026b1bd5 100644 --- a/src/tests/routes/me/tokens/create.rs +++ b/src/tests/routes/me/tokens/create.rs @@ -24,10 +24,7 @@ async fn create_token_invalid_request() { let invalid: &[u8] = br#"{ "name": "" }"#; let response = user.put::<()>("/api/v1/me/tokens", invalid).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid new token request: Error(\"missing field `api_token`\", line: 1, column: 14)"}]}"#); assert!(app.emails().is_empty()); } @@ -37,10 +34,7 @@ async fn create_token_no_name() { let empty_name: &[u8] = br#"{ "api_token": { "name": "" } }"#; let response = user.put::<()>("/api/v1/me/tokens", empty_name).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "name must have a value" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"name must have a value"}]}"#); assert!(app.emails().is_empty()); } @@ -55,10 +49,7 @@ async fn create_token_exceeded_tokens_per_user() { }); let response = user.put::<()>("/api/v1/me/tokens", NEW_BAR).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "maximum tokens per user is: 500" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"maximum tokens per user is: 500"}]}"#); assert!(app.emails().is_empty()); } @@ -121,10 +112,7 @@ async fn cannot_create_token_with_token() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "cannot use an API token to create a new API token" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"cannot use an API token to create a new API token"}]}"#); assert!(app.emails().is_empty()); } @@ -229,10 +217,7 @@ async fn create_token_with_empty_crate_scope() { .put::<()>("/api/v1/me/tokens", serde_json::to_vec(&json).unwrap()) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid crate scope" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid crate scope"}]}"#); assert!(app.emails().is_empty()); } @@ -252,10 +237,7 @@ async fn create_token_with_invalid_endpoint_scope() { .put::<()>("/api/v1/me/tokens", serde_json::to_vec(&json).unwrap()) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "invalid endpoint scope" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"invalid endpoint scope"}]}"#); assert!(app.emails().is_empty()); } diff --git a/src/tests/routes/me/tokens/delete_current.rs b/src/tests/routes/me/tokens/delete_current.rs index 95f67f1864c..a9eb1d0a8d3 100644 --- a/src/tests/routes/me/tokens/delete_current.rs +++ b/src/tests/routes/me/tokens/delete_current.rs @@ -59,10 +59,7 @@ async fn revoke_current_token_with_cookie_user() { // Revoke the token let response = user.delete::<()>("/api/v1/tokens/current").await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "token not provided" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"token not provided"}]}"#); // Ensure that the token still exists in the database after the failed request app.db(|conn| { diff --git a/src/tests/routes/me/tokens/list.rs b/src/tests/routes/me/tokens/list.rs index 9c74cf886ca..c86c63af1a1 100644 --- a/src/tests/routes/me/tokens/list.rs +++ b/src/tests/routes/me/tokens/list.rs @@ -4,6 +4,7 @@ use chrono::{Duration, Utc}; use crates_io::models::token::{CrateScope, EndpointScope}; use crates_io::models::ApiToken; use http::StatusCode; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn list_logged_out() { @@ -22,9 +23,7 @@ async fn list_empty() { let (_, _, user) = TestApp::init().with_user(); let response = user.get::<()>("/api/v1/me/tokens").await; assert_eq!(response.status(), StatusCode::OK); - let json = response.json(); - let response_tokens = json["api_tokens"].as_array().unwrap(); - assert_eq!(response_tokens.len(), 0); + assert_snapshot!(response.text(), @r#"{"api_tokens":[]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/routes/me/updates.rs b/src/tests/routes/me/updates.rs index 362b7de3c3a..3b5e878abe9 100644 --- a/src/tests/routes/me/updates.rs +++ b/src/tests/routes/me/updates.rs @@ -7,6 +7,7 @@ use diesel::prelude::*; use diesel::update; use googletest::prelude::*; use http::StatusCode; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn api_token_cannot_get_user_updates() { @@ -98,8 +99,5 @@ async fn following() { .get_with_query::<()>("/api/v1/me/updates", "page=0") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "page indexing starts from 1, page 0 is invalid" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"page indexing starts from 1, page 0 is invalid"}]}"#); } diff --git a/src/tests/routes/session/authorize.rs b/src/tests/routes/session/authorize.rs index 9db0f70b1a3..628510eb44b 100644 --- a/src/tests/routes/session/authorize.rs +++ b/src/tests/routes/session/authorize.rs @@ -1,13 +1,11 @@ use crate::util::{RequestHelper, TestApp}; use http::StatusCode; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn access_token_needs_data() { let (_, anon) = TestApp::init().empty(); let response = anon.get::<()>("/api/private/session/authorize").await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "Failed to deserialize query string: missing field `code`" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"Failed to deserialize query string: missing field `code`"}]}"#); } diff --git a/src/tests/routes/users/update.rs b/src/tests/routes/users/update.rs index 27c3464c559..d0b08b5ebf4 100644 --- a/src/tests/routes/users/update.rs +++ b/src/tests/routes/users/update.rs @@ -43,10 +43,7 @@ async fn test_empty_email_not_added() { let response = user.update_email_more_control(model.id, Some("")).await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "empty email rejected" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"empty email rejected"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -91,10 +88,7 @@ async fn test_other_users_cannot_change_my_email() { ) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "current user does not match requested user" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"current user does not match requested user"}]}"#); let response = anon .update_email_more_control( diff --git a/src/tests/snapshots/all__owners__modify_multiple_owners-2.snap b/src/tests/snapshots/all__owners__modify_multiple_owners-6.snap similarity index 100% rename from src/tests/snapshots/all__owners__modify_multiple_owners-2.snap rename to src/tests/snapshots/all__owners__modify_multiple_owners-6.snap diff --git a/src/tests/team.rs b/src/tests/team.rs index 8fa2d35de81..a21a2524184 100644 --- a/src/tests/team.rs +++ b/src/tests/team.rs @@ -36,10 +36,7 @@ async fn not_github() { .add_named_owner("foo_not_github", "dropbox:foo:foo") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "unknown organization handler, only 'github:org:team' is supported" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"unknown organization handler, only 'github:org:team' is supported"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -54,10 +51,7 @@ async fn weird_name() { .add_named_owner("foo_weird_name", "github:foo/../bar:wut") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "organization cannot contain special characters like /" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"organization cannot contain special characters like /"}]}"#); } /// Test adding team without second `:` @@ -71,10 +65,7 @@ async fn one_colon() { let response = token.add_named_owner("foo_one_colon", "github:foo").await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "missing github team argument; format is github:org:team" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"missing github team argument; format is github:org:team"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -89,17 +80,7 @@ async fn add_nonexistent_team() { .add_named_owner("foo_add_nonexistent", "github:test-org:this-does-not-exist") .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ - "errors": [{ - "detail": - "could not find the github team test-org/this-does-not-exist. \ - Make sure that you have the right permissions in GitHub. \ - See https://doc.rust-lang.org/cargo/reference/publishing.html#github-permissions" - }] - }) - ); + assert_snapshot!(response.text(), @r##"{"errors":[{"detail":"could not find the github team test-org/this-does-not-exist. Make sure that you have the right permissions in GitHub. See https://doc.rust-lang.org/cargo/reference/publishing.html#github-permissions"}]}"##); } /// Test adding a renamed team @@ -212,10 +193,7 @@ async fn add_team_as_non_member() { .add_named_owner("foo_team_non_member", "github:test-org:core") .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "only members of a team or organization owners can add it as an owner" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"only members of a team or organization owners can add it as an owner"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -240,10 +218,7 @@ async fn remove_team_as_named_owner() { .remove_named_owner("foo_remove_team", username) .await; assert_eq!(response.status(), StatusCode::BAD_REQUEST); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"cannot remove all individual owners of a crate. Team member don't have permission to modify owners, so at least one individual owner is required."}]}"#); token_on_both_teams .remove_named_owner("foo_remove_team", "github:test-org:core") @@ -254,10 +229,7 @@ async fn remove_team_as_named_owner() { let crate_to_publish = PublishBuilder::new("foo_remove_team", "2.0.0"); let response = user_on_one_team.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing."}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -283,10 +255,7 @@ async fn remove_team_as_team_owner() { .remove_named_owner("foo_remove_team_owner", "github:test-org:all") .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "team members don't have permission to modify owners" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"team members don't have permission to modify owners"}]}"#); let user_org_owner = app.db_new_user("user-org-owner"); let token_org_owner = user_org_owner.db_new_token("arbitrary token name"); @@ -294,10 +263,7 @@ async fn remove_team_as_team_owner() { .remove_named_owner("foo_remove_team_owner", "github:test-org:all") .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "only owners have permission to modify owners" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"only owners have permission to modify owners"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -345,10 +311,7 @@ async fn publish_not_owned() { let crate_to_publish = PublishBuilder::new("foo_not_owned", "2.0.0"); let response = user_on_one_team.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing."}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -371,10 +334,7 @@ async fn publish_org_owner_owned() { let crate_to_publish = PublishBuilder::new("foo_not_owned", "2.0.0"); let response = user_org_owner.publish_crate(crate_to_publish).await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing." }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"this crate exists but you don't seem to be an owner. If you believe this is a mistake, perhaps you need to accept an invitation to be an owner before publishing."}]}"#); } /// Test trying to publish a krate we do own (but only because of teams) @@ -427,10 +387,7 @@ async fn add_owners_as_org_owner() { .add_named_owner("foo_add_owner", "arbitrary_username") .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "only owners have permission to modify owners" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"only owners have permission to modify owners"}]}"#); } #[tokio::test(flavor = "multi_thread")] @@ -455,10 +412,7 @@ async fn add_owners_as_team_owner() { .add_named_owner("foo_add_owner", "arbitrary_username") .await; assert_eq!(response.status(), StatusCode::FORBIDDEN); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": "team members don't have permission to modify owners" }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"team members don't have permission to modify owners"}]}"#); } #[tokio::test(flavor = "multi_thread")] diff --git a/src/tests/token.rs b/src/tests/token.rs index 4fe513ce126..d96b5a6f308 100644 --- a/src/tests/token.rs +++ b/src/tests/token.rs @@ -1,8 +1,9 @@ use crate::util::MockRequestExt; use crate::{RequestHelper, TestApp}; -use crates_io::{models::ApiToken, util::errors::TOKEN_FORMAT_ERROR, views::EncodableMe}; +use crates_io::{models::ApiToken, views::EncodableMe}; use diesel::prelude::*; use http::{header, StatusCode}; +use insta::assert_snapshot; #[tokio::test(flavor = "multi_thread")] async fn using_token_updates_last_used_at() { @@ -37,8 +38,5 @@ async fn old_tokens_give_specific_error_message() { request.header(header::AUTHORIZATION, "oldtoken"); let response = anon.run::<()>(request).await; assert_eq!(response.status(), StatusCode::UNAUTHORIZED); - assert_eq!( - response.json(), - json!({ "errors": [{ "detail": TOKEN_FORMAT_ERROR }] }) - ); + assert_snapshot!(response.text(), @r#"{"errors":[{"detail":"The given API token does not match the format used by crates.io. Tokens generated before 2020-07-14 were generated with an insecure random number generator, and have been revoked. You can generate a new token at https://crates.io/me. For more information please see https://blog.rust-lang.org/2020/07/14/crates-io-security-advisory.html. We apologize for any inconvenience."}]}"#); }