Skip to content

Commit d20f081

Browse files
committed
Auto merge of #3097 - Turbo87:errors, r=jtgeibel
tests: Use `assert_eq!()` to check error response payload content This PR continues #3066 and converts the remaining tests to use the same pattern of using `assert_eq!()` and the `json!()` macro to assert on the exact structure and content of the error responses. r? `@jtgeibel`
2 parents 365928d + 6013249 commit d20f081

File tree

13 files changed

+271
-309
lines changed

13 files changed

+271
-309
lines changed

src/tests/account_lock.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@ fn account_locked_indefinitely() {
2626
let (app, _anon, user) = TestApp::init().with_user();
2727
lock_account(&app, user.as_model().id, None);
2828

29-
user.get::<()>(URL)
30-
.bad_with_status(StatusCode::FORBIDDEN)
31-
.assert_error(&format!(
32-
"This account is indefinitely locked. Reason: {}",
33-
LOCK_REASON
34-
));
29+
let response = user.get::<()>(URL);
30+
response.assert_status(StatusCode::FORBIDDEN);
31+
32+
let error_message = format!(
33+
"This account is indefinitely locked. Reason: {}",
34+
LOCK_REASON
35+
);
36+
assert_eq!(
37+
response.json(),
38+
json!({ "errors": [{ "detail": error_message }] })
39+
);
3540
}
3641

3742
#[test]
@@ -42,12 +47,17 @@ fn account_locked_with_future_expiry() {
4247
lock_account(&app, user.as_model().id, Some(until));
4348

4449
let until = until.format("%Y-%m-%d at %H:%M:%S UTC");
45-
user.get::<()>(URL)
46-
.bad_with_status(StatusCode::FORBIDDEN)
47-
.assert_error(&format!(
48-
"This account is locked until {}. Reason: {}",
49-
until, LOCK_REASON,
50-
));
50+
let response = user.get::<()>(URL);
51+
response.assert_status(StatusCode::FORBIDDEN);
52+
53+
let error_message = format!(
54+
"This account is locked until {}. Reason: {}",
55+
until, LOCK_REASON,
56+
);
57+
assert_eq!(
58+
response.json(),
59+
json!({ "errors": [{ "detail": error_message }] })
60+
);
5161
}
5262

5363
#[test]

src/tests/all.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ extern crate serde;
1111
#[macro_use]
1212
extern crate serde_json;
1313

14-
use crate::util::{Bad, RequestHelper, TestApp};
14+
use crate::util::{RequestHelper, TestApp};
1515
use cargo_registry::{
1616
models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
1717
schema::crate_owners,
@@ -182,14 +182,6 @@ fn req(method: conduit::Method, path: &str) -> MockRequest {
182182
request
183183
}
184184

185-
fn bad_resp(r: &mut AppResponse) -> Option<Bad> {
186-
let bad = json::<Bad>(r);
187-
if bad.errors.is_empty() {
188-
return None;
189-
}
190-
Some(bad)
191-
}
192-
193185
fn json<T>(r: &mut AppResponse) -> T
194186
where
195187
for<'de> T: serde::Deserialize<'de>,

src/tests/krate/dependencies.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ fn dependencies() {
2626
.good();
2727
assert_eq!(deps.dependencies[0].crate_id, "bar_deps");
2828

29-
anon.get::<()>("/api/v1/crates/foo_deps/1.0.2/dependencies")
30-
.bad_with_status(StatusCode::OK);
29+
let response = anon.get::<()>("/api/v1/crates/foo_deps/1.0.2/dependencies");
30+
response.assert_status(StatusCode::OK);
31+
assert_eq!(
32+
response.json(),
33+
json!({ "errors": [{ "detail": "crate `foo_deps` does not have a version `1.0.2`" }] })
34+
);
3135
}

src/tests/krate/publish.rs

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,15 @@ fn invalid_names() {
8686

8787
let bad_name = |name: &str, error_message: &str| {
8888
let crate_to_publish = PublishBuilder::new(name).version("1.0.0");
89-
let json = token
90-
.enqueue_publish(crate_to_publish)
91-
.bad_with_status(StatusCode::OK);
92-
93-
assert!(
94-
json.errors[0].detail.contains(error_message,),
95-
"{:?}",
96-
json.errors
97-
);
89+
let response = token.enqueue_publish(crate_to_publish);
90+
response.assert_status(StatusCode::OK);
91+
92+
let json = response.json();
93+
let json = json.as_object().unwrap();
94+
let errors = json.get("errors").unwrap().as_array().unwrap();
95+
let first_error = errors.first().unwrap().as_object().unwrap();
96+
let detail = first_error.get("detail").unwrap().as_str().unwrap();
97+
assert!(detail.contains(error_message), "{:?}", detail);
9898
};
9999

100100
let error_message = "expected a valid crate name";
@@ -251,9 +251,13 @@ fn reject_new_krate_with_non_exact_dependency() {
251251
let crate_to_publish = PublishBuilder::new("new_dep")
252252
.version("1.0.0")
253253
.dependency(dependency);
254-
token
255-
.enqueue_publish(crate_to_publish)
256-
.bad_with_status(StatusCode::OK);
254+
255+
let response = token.enqueue_publish(crate_to_publish);
256+
response.assert_status(StatusCode::OK);
257+
assert_eq!(
258+
response.json(),
259+
json!({ "errors": [{ "detail": "no known crate named `foo_dep`" }] })
260+
);
257261
}
258262

259263
#[test]
@@ -696,19 +700,28 @@ fn bad_keywords() {
696700
let (_, _, _, token) = TestApp::init().with_token();
697701
let crate_to_publish =
698702
PublishBuilder::new("foo_bad_key").keyword("super-long-keyword-name-oh-no");
699-
token
700-
.enqueue_publish(crate_to_publish)
701-
.bad_with_status(StatusCode::OK);
703+
let response = token.enqueue_publish(crate_to_publish);
704+
response.assert_status(StatusCode::OK);
705+
assert_eq!(
706+
response.json(),
707+
json!({ "errors": [{ "detail": "invalid upload request: invalid length 29, expected a keyword with less than 20 characters at line 1 column 221" }] })
708+
);
702709

703710
let crate_to_publish = PublishBuilder::new("foo_bad_key").keyword("?@?%");
704-
token
705-
.enqueue_publish(crate_to_publish)
706-
.bad_with_status(StatusCode::OK);
711+
let response = token.enqueue_publish(crate_to_publish);
712+
response.assert_status(StatusCode::OK);
713+
assert_eq!(
714+
response.json(),
715+
json!({ "errors": [{ "detail": "invalid upload request: invalid value: string \"?@?%\", expected a valid keyword specifier at line 1 column 196" }] })
716+
);
707717

708718
let crate_to_publish = PublishBuilder::new("foo_bad_key").keyword("áccênts");
709-
token
710-
.enqueue_publish(crate_to_publish)
711-
.bad_with_status(StatusCode::OK);
719+
let response = token.enqueue_publish(crate_to_publish);
720+
response.assert_status(StatusCode::OK);
721+
assert_eq!(
722+
response.json(),
723+
json!({ "errors": [{ "detail": "invalid upload request: invalid value: string \"áccênts\", expected a valid keyword specifier at line 1 column 201" }] })
724+
);
712725
}
713726

714727
#[test]

src/tests/krate/search.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -676,19 +676,19 @@ fn pagination_parameters_only_accept_integers() {
676676
CrateBuilder::new("pagination_links_3", user.id).expect_build(conn);
677677
});
678678

679-
let invalid_per_page_json = anon
680-
.get_with_query::<()>("/api/v1/crates", "page=1&per_page=100%22%EF%BC%8Cexception")
681-
.bad_with_status(StatusCode::BAD_REQUEST);
679+
let response =
680+
anon.get_with_query::<()>("/api/v1/crates", "page=1&per_page=100%22%EF%BC%8Cexception");
681+
response.assert_status(StatusCode::BAD_REQUEST);
682682
assert_eq!(
683-
invalid_per_page_json.errors[0].detail,
684-
"invalid digit found in string"
683+
response.json(),
684+
json!({ "errors": [{ "detail": "invalid digit found in string" }] })
685685
);
686686

687-
let invalid_page_json = anon
688-
.get_with_query::<()>("/api/v1/crates", "page=100%22%EF%BC%8Cexception&per_page=1")
689-
.bad_with_status(StatusCode::BAD_REQUEST);
687+
let response =
688+
anon.get_with_query::<()>("/api/v1/crates", "page=100%22%EF%BC%8Cexception&per_page=1");
689+
response.assert_status(StatusCode::BAD_REQUEST);
690690
assert_eq!(
691-
invalid_page_json.errors[0].detail,
692-
"invalid digit found in string"
691+
response.json(),
692+
json!({ "errors": [{ "detail": "invalid digit found in string" }] })
693693
);
694694
}

src/tests/krate/yanking.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,11 @@ fn yank_by_a_non_owner_fails() {
109109
.expect_build(conn);
110110
});
111111

112-
let json = token
113-
.yank("foo_not", "1.0.0")
114-
.bad_with_status(StatusCode::OK);
112+
let response = token.yank("foo_not", "1.0.0");
113+
response.assert_status(StatusCode::OK);
115114
assert_eq!(
116-
json.errors[0].detail,
117-
"must already be an owner to yank or unyank"
115+
response.json(),
116+
json!({ "errors": [{ "detail": "must already be an owner to yank or unyank" }] })
118117
);
119118
}
120119

src/tests/owners.rs

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -135,28 +135,30 @@ fn owners_can_remove_self() {
135135
.db(|conn| CrateBuilder::new("owners_selfremove", user.as_model().id).expect_build(conn));
136136

137137
// Deleting yourself when you're the only owner isn't allowed.
138-
let json = token
139-
.remove_named_owner("owners_selfremove", username)
140-
.bad_with_status(StatusCode::OK);
141-
assert!(json.errors[0]
142-
.detail
143-
.contains("cannot remove all individual owners of a crate"));
138+
let response = token.remove_named_owner("owners_selfremove", username);
139+
response.assert_status(StatusCode::OK);
140+
assert_eq!(
141+
response.json(),
142+
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." }] })
143+
);
144144

145145
create_and_add_owner(&app, &token, "secondowner", &krate);
146146

147147
// Deleting yourself when there are other owners is allowed.
148-
let json = token
149-
.remove_named_owner("owners_selfremove", username)
150-
.good();
151-
assert!(json.ok);
148+
let response = token.remove_named_owner("owners_selfremove", username);
149+
response.assert_status(StatusCode::OK);
150+
assert_eq!(
151+
response.json(),
152+
json!({ "msg": "owners successfully removed", "ok": true })
153+
);
152154

153155
// After you delete yourself, you no longer have permisions to manage the crate.
154-
let json = token
155-
.remove_named_owner("owners_selfremove", username)
156-
.bad_with_status(StatusCode::OK);
157-
assert!(json.errors[0]
158-
.detail
159-
.contains("only owners have permission to modify owners",));
156+
let response = token.remove_named_owner("owners_selfremove", username);
157+
response.assert_status(StatusCode::OK);
158+
assert_eq!(
159+
response.json(),
160+
json!({ "errors": [{ "detail": "only owners have permission to modify owners" }] })
161+
);
160162
}
161163

162164
// Verify consistency when adidng or removing multiple owners in a single request.
@@ -172,35 +174,46 @@ fn modify_multiple_owners() {
172174
let user3 = create_and_add_owner(&app, &token, "user3", &krate);
173175

174176
// Deleting all owners is not allowed.
175-
let json = token
176-
.remove_named_owners("owners_multiple", &[username, "user2", "user3"])
177-
.bad_with_status(StatusCode::OK);
178-
assert!(&json.errors[0]
179-
.detail
180-
.contains("cannot remove all individual owners of a crate"));
177+
let response = token.remove_named_owners("owners_multiple", &[username, "user2", "user3"]);
178+
response.assert_status(StatusCode::OK);
179+
assert_eq!(
180+
response.json(),
181+
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." }] })
182+
);
181183
assert_eq!(app.db(|conn| krate.owners(&conn).unwrap()).len(), 3);
182184

183185
// Deleting two owners at once is allowed.
184-
let json = token
185-
.remove_named_owners("owners_multiple", &["user2", "user3"])
186-
.good();
187-
assert!(json.ok);
186+
let response = token.remove_named_owners("owners_multiple", &["user2", "user3"]);
187+
response.assert_status(StatusCode::OK);
188+
assert_eq!(
189+
response.json(),
190+
json!({ "msg": "owners successfully removed", "ok": true })
191+
);
188192
assert_eq!(app.db(|conn| krate.owners(&conn).unwrap()).len(), 1);
189193

190194
// Adding multiple users fails if one of them already is an owner.
191-
let json = token
192-
.add_named_owners("owners_multiple", &["user2", username])
193-
.bad_with_status(StatusCode::OK);
194-
assert!(&json.errors[0].detail.contains("is already an owner"));
195+
let response = token.add_named_owners("owners_multiple", &["user2", username]);
196+
response.assert_status(StatusCode::OK);
197+
assert_eq!(
198+
response.json(),
199+
json!({ "errors": [{ "detail": "`foo` is already an owner" }] })
200+
);
195201
assert_eq!(app.db(|conn| krate.owners(&conn).unwrap()).len(), 1);
196202

197203
// Adding multiple users at once succeeds.
198-
let json = token
199-
.add_named_owners("owners_multiple", &["user2", "user3"])
200-
.good();
201-
assert!(json.ok);
204+
let response = token.add_named_owners("owners_multiple", &["user2", "user3"]);
205+
response.assert_status(StatusCode::OK);
206+
assert_eq!(
207+
response.json(),
208+
json!({
209+
"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",
210+
"ok": true,
211+
})
212+
);
213+
202214
user2.accept_ownership_invitation(&krate.name, krate.id);
203215
user3.accept_ownership_invitation(&krate.name, krate.id);
216+
204217
assert_eq!(app.db(|conn| krate.owners(&conn).unwrap()).len(), 3);
205218
}
206219

0 commit comments

Comments
 (0)