Skip to content

Commit abf5267

Browse files
committed
Rename MockUserSession to TestApp and move to a new util module
1 parent 43ad51d commit abf5267

File tree

12 files changed

+531
-474
lines changed

12 files changed

+531
-474
lines changed

src/controllers/user/me.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use util::bad_request;
88

99
use models::{Email, Follow, NewEmail, User, Version};
1010
use schema::{crates, emails, follows, users, versions};
11-
use views::{EncodablePrivateUser, EncodableVersion};
11+
use views::{EncodableMe, EncodableVersion};
1212

1313
/// Handles the `GET /me` route.
1414
pub fn me(req: &mut dyn Request) -> CargoResult<Response> {
@@ -40,11 +40,7 @@ pub fn me(req: &mut dyn Request) -> CargoResult<Response> {
4040
let verification_sent = verified || verification_sent;
4141
let user = User { email, ..user };
4242

43-
#[derive(Serialize)]
44-
struct R {
45-
user: EncodablePrivateUser,
46-
}
47-
Ok(req.json(&R {
43+
Ok(req.json(&EncodableMe {
4844
user: user.encodable_private(verified, verification_sent),
4945
}))
5046
}

src/tests/all.rs

Lines changed: 6 additions & 277 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,14 @@ use cargo_registry::app::App;
3838
use cargo_registry::middleware::current_user::AuthenticationSource;
3939
use cargo_registry::Replica;
4040
use chrono::Utc;
41-
use conduit::{Handler, Method, Request};
41+
use conduit::{Method, Request};
4242
use conduit_test::MockRequest;
4343
use diesel::prelude::*;
4444
use flate2::write::GzEncoder;
4545
use flate2::Compression;
4646

47-
pub use cargo_registry::{models, schema, views};
47+
use cargo_registry::{models, schema, views};
48+
use util::{Bad, RequestHelper, TestApp};
4849

4950
use models::{Crate, CrateDownload, CrateOwner, Dependency, Keyword, Team, User, Version};
5051
use models::{NewCategory, NewCrate, NewTeam, NewUser, NewVersion};
@@ -61,13 +62,6 @@ macro_rules! t {
6162
};
6263
}
6364

64-
// TODO: Remove, this is equivalent to t!
65-
macro_rules! t_resp {
66-
($e:expr) => {
67-
t!($e)
68-
};
69-
}
70-
7165
macro_rules! ok_resp {
7266
($e:expr) => {{
7367
let resp = t!($e);
@@ -88,73 +82,6 @@ macro_rules! bad_resp {
8882
}};
8983
}
9084

91-
#[derive(Deserialize, Debug)]
92-
struct Error {
93-
detail: String,
94-
}
95-
#[derive(Deserialize)]
96-
struct Bad {
97-
errors: Vec<Error>,
98-
}
99-
100-
type DieselConnection =
101-
diesel::r2d2::PooledConnection<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
102-
type ResponseResult = Result<conduit::Response, Box<std::error::Error + Send>>;
103-
104-
#[must_use]
105-
struct Response<T> {
106-
response: conduit::Response,
107-
callback_on_good: Option<Box<Fn(&T)>>,
108-
}
109-
110-
impl<T> Response<T>
111-
where
112-
for<'de> T: serde::Deserialize<'de>,
113-
{
114-
pub fn new(response: ResponseResult) -> Self {
115-
Self {
116-
response: t!(response),
117-
callback_on_good: None,
118-
}
119-
}
120-
121-
pub fn with_callback(response: ResponseResult, callback_on_good: Box<Fn(&T)>) -> Self {
122-
Self {
123-
response: t!(response),
124-
callback_on_good: Some(callback_on_good),
125-
}
126-
}
127-
128-
pub fn good(mut self) -> T {
129-
if !ok_resp(&self.response) {
130-
panic!("bad response: {:?}", self.response.status);
131-
}
132-
let good = json(&mut self.response);
133-
if let Some(callback) = self.callback_on_good {
134-
callback(&good)
135-
}
136-
good
137-
}
138-
139-
pub fn bad_with_status(&mut self, code: u32) -> Bad {
140-
assert_eq!(self.response.status.0, code);
141-
match bad_resp(&mut self.response) {
142-
None => panic!("ok response: {:?}", self.response.status),
143-
Some(b) => b,
144-
}
145-
}
146-
}
147-
148-
impl Response<()> {
149-
pub fn assert_not_found(&self) {
150-
assert_eq!((404, "Not Found"), self.response.status);
151-
}
152-
153-
pub fn assert_forbidden(&self) {
154-
assert_eq!((403, "Forbidden"), self.response.status);
155-
}
156-
}
157-
15885
mod badge;
15986
mod categories;
16087
mod category;
@@ -167,10 +94,11 @@ mod schema_details;
16794
mod team;
16895
mod token;
16996
mod user;
97+
mod util;
17098
mod version;
17199

172100
#[derive(Deserialize, Debug)]
173-
struct GoodCrate {
101+
pub struct GoodCrate {
174102
#[serde(rename = "crate")]
175103
krate: EncodableCrate,
176104
warnings: Warnings,
@@ -810,205 +738,6 @@ fn new_crate_to_body_with_tarball(new_crate: &u::NewCrate, tarball: &[u8]) -> Ve
810738
body
811739
}
812740

813-
/// A struct representing a user's session to be used for the duration of a test.
814-
/// This injects requests directly into the router, so doesn't quite exercise the application
815-
/// exactly as in production, but it's close enough for most testing purposes.
816-
/// Has useful methods for making common HTTP requests.
817-
struct MockUserSession {
818-
app: Arc<App>,
819-
// The bomb needs to be held in scope until the end of the test.
820-
_bomb: record::Bomb,
821-
middle: conduit_middleware::MiddlewareBuilder,
822-
user: Option<User>,
823-
}
824-
825-
impl MockUserSession {
826-
/// Create a session with no logged in user.
827-
pub fn anonymous() -> Self {
828-
let (bomb, app, middle) = app();
829-
MockUserSession {
830-
app,
831-
_bomb: bomb,
832-
middle,
833-
user: None,
834-
}
835-
}
836-
837-
/// Create a session logged in with an arbitrary user.
838-
pub fn logged_in() -> Self {
839-
let (bomb, app, middle) = app();
840-
let conn = app.diesel_database.get().unwrap();
841-
let user = new_user("foo").create_or_update(&conn).unwrap();
842-
843-
MockUserSession {
844-
app,
845-
_bomb: bomb,
846-
middle,
847-
user: Some(user),
848-
}
849-
}
850-
851-
/// Obtain the database connection and pass it to the closure
852-
///
853-
/// Within each test, the connection pool only has 1 connection so it is necessary to drop the
854-
/// connection before making any API calls. Once the closure returns, the connection is
855-
/// dropped, ensuring it is available for any API calls.
856-
pub fn db<T, F: FnOnce(&DieselConnection) -> T>(&self, f: F) -> T {
857-
let conn = self.app.diesel_database.get().unwrap();
858-
f(&conn)
859-
}
860-
861-
/// Build a MockRequest with a User if one is present
862-
fn request_builder(&self, method: Method, path: &str) -> MockRequest {
863-
let mut request = MockRequest::new(method, path);
864-
if let Some(ref user) = self.user {
865-
request.mut_extensions().insert(user.clone());
866-
request
867-
.mut_extensions()
868-
.insert(AuthenticationSource::SessionCookie);
869-
}
870-
request
871-
}
872-
873-
/// Issue a GET request as the current user
874-
pub fn get<T>(&self, path: &str) -> Response<T>
875-
where
876-
for<'de> T: serde::Deserialize<'de>,
877-
{
878-
let mut request = self.request_builder(Method::Get, path);
879-
Response::new(self.middle.call(&mut request))
880-
}
881-
882-
/// Issue a GET request as the current user
883-
pub fn get_with_query<T>(&self, path: &str, query: &str) -> Response<T>
884-
where
885-
for<'de> T: serde::Deserialize<'de>,
886-
{
887-
let mut request = self.request_builder(Method::Get, path);
888-
request.with_query(query);
889-
Response::new(self.middle.call(&mut request))
890-
}
891-
892-
/// Issue a PUT request as the current user
893-
pub fn put<T>(&self, path: &str, body: &[u8]) -> Response<T>
894-
where
895-
for<'de> T: serde::Deserialize<'de>,
896-
{
897-
let mut builder = self.request_builder(Method::Put, path);
898-
let request = builder.with_body(body);
899-
Response::new(self.middle.call(request))
900-
}
901-
902-
/// Issue a DELETE request as the current user
903-
pub fn delete<T>(&self, path: &str) -> Response<T>
904-
where
905-
for<'de> T: serde::Deserialize<'de>,
906-
{
907-
let mut request = self.request_builder(Method::Delete, path);
908-
Response::new(self.middle.call(&mut request))
909-
}
910-
911-
/// Log out the currently logged in user.
912-
pub fn logout(&mut self) {
913-
self.user = None;
914-
}
915-
916-
/// Using the same session, log in as a different user.
917-
pub fn log_in_as(&mut self, user: User) {
918-
self.user = Some(user);
919-
}
920-
921-
/// Create and log in as a new user, returning a reference to the user
922-
pub fn log_in_as_new(&mut self, user: &str) -> &User {
923-
let user = self.db(|conn| new_user(user).create_or_update(conn).unwrap());
924-
self.user = Some(user);
925-
self.user()
926-
}
927-
928-
/// Return a reference to the current user
929-
///
930-
/// # Panics
931-
///
932-
/// This function panics if there is no current user.
933-
pub fn user(&self) -> &User {
934-
self.user.as_ref().unwrap()
935-
}
936-
937-
/// Publish the crate as specified by the given builder
938-
pub fn publish(&self, publish_builder: PublishBuilder) -> Response<GoodCrate> {
939-
let krate_name = publish_builder.krate_name.clone();
940-
let mut builder = self.request_builder(Method::Put, "/api/v1/crates/new");
941-
let request = builder.with_body(&publish_builder.body());
942-
let response = self.middle.call(request);
943-
let callback_on_good = move |json: &GoodCrate| assert_eq!(json.krate.name, krate_name);
944-
Response::with_callback(response, Box::new(callback_on_good))
945-
}
946-
947-
/// Request the JSON used for a crate's page.
948-
pub fn show_crate(&mut self, krate_name: &str) -> CrateResponse {
949-
let url = format!("/api/v1/crates/{}", krate_name);
950-
self.get(&url).good()
951-
}
952-
953-
/// Yank the specified version of the specified crate.
954-
pub fn yank(&mut self, krate_name: &str, version: &str) -> Response<OkBool> {
955-
let url = format!("/api/v1/crates/{}/{}/yank", krate_name, version);
956-
let mut request = self.request_builder(Method::Delete, &url);
957-
Response::new(self.middle.call(&mut request))
958-
}
959-
960-
/// Add a user as an owner for a crate.
961-
pub fn add_owner(&mut self, krate_name: &str, user: &User) {
962-
let url = format!("/api/v1/crates/{}/owners", krate_name);
963-
let body = format!("{{\"users\":[\"{}\"]}}", user.gh_login);
964-
let mut builder = self.request_builder(Method::Put, &url);
965-
let request = builder.with_body(body.as_bytes());
966-
967-
let response: OkBool = Response::new(self.middle.call(request)).good();
968-
assert!(response.ok);
969-
}
970-
971-
/// As the currently logged in user, accept an invitation to become an owner of the named
972-
/// crate.
973-
pub fn accept_ownership_invitation(&mut self, krate_name: &str) {
974-
use views::InvitationResponse;
975-
976-
let krate_id = self.db(|conn| Crate::by_name(krate_name).first::<Crate>(conn).unwrap().id);
977-
978-
let body = json!({
979-
"crate_owner_invite": {
980-
"invited_by_username": "",
981-
"crate_name": krate_name,
982-
"crate_id": krate_id,
983-
"created_at": "",
984-
"accepted": true
985-
}
986-
});
987-
988-
let url = format!("/api/v1/me/crate_owner_invitations/{}", krate_id);
989-
let mut builder = self.request_builder(Method::Put, &url);
990-
let request = builder.with_body(body.to_string().as_bytes());
991-
992-
#[derive(Deserialize)]
993-
struct CrateOwnerInvitation {
994-
crate_owner_invitation: InvitationResponse,
995-
}
996-
997-
let crate_owner_invite: CrateOwnerInvitation =
998-
Response::new(self.middle.call(request)).good();
999-
assert!(crate_owner_invite.crate_owner_invitation.accepted);
1000-
assert_eq!(crate_owner_invite.crate_owner_invitation.crate_id, krate_id);
1001-
}
1002-
1003-
/// Get the crates owned by the specified user.
1004-
pub fn crates_owned_by(&mut self, user: &User) -> CrateList {
1005-
let query = format!("user_id={}", user.id);
1006-
let mut builder = self.request_builder(Method::Get, "/api/v1/crates");
1007-
let request = builder.with_query(&query);
1008-
Response::new(self.middle.call(request)).good()
1009-
}
1010-
}
1011-
1012741
lazy_static! {
1013742
static ref EMPTY_TARBALL_BYTES: Vec<u8> = {
1014743
let mut empty_tarball = vec![];
@@ -1024,7 +753,7 @@ lazy_static! {
1024753
/// A builder for constructing a crate for the purposes of testing publishing. If you only need
1025754
/// a crate to exist and don't need to test behavior caused by the publish request, inserting
1026755
/// a crate into the database directly by using CrateBuilder will be faster.
1027-
struct PublishBuilder {
756+
pub struct PublishBuilder {
1028757
pub krate_name: String,
1029758
version: semver::Version,
1030759
tarball: Vec<u8>,

src/tests/badge.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::HashMap;
22

33
use models::{Badge, Crate, MaintenanceStatus};
4-
use {app, new_user, CrateBuilder, DieselConnection};
4+
use {app, new_user, util::DieselConnection, CrateBuilder};
55

66
struct BadgeRef {
77
appveyor: Badge,

src/tests/category.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fn show() {
5959

6060
// Return not found if a category doesn't exist
6161
let mut req = req(Method::Get, "/api/v1/categories/foo-bar");
62-
let response = t_resp!(middle.call(&mut req));
62+
let response = t!(middle.call(&mut req));
6363
assert_eq!(response.status.0, 404);
6464

6565
// Create a category and a subcategory

0 commit comments

Comments
 (0)