Skip to content

Commit 32e1a4f

Browse files
authored
Merge pull request #5535 from Turbo87/route-tests-module
tests: Extract routes module
2 parents b5b01d2 + 8803c40 commit 32e1a4f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+871
-782
lines changed

src/tests/all.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,14 @@ mod authentication;
3232
mod blocked_routes;
3333
mod builders;
3434
mod categories;
35-
mod category;
3635
mod dump_db;
37-
mod keyword;
3836
mod krate;
39-
mod metrics;
4037
mod not_found_error;
4138
mod owners;
39+
mod pagination;
4240
mod read_only_mode;
4341
mod record;
42+
mod routes;
4443
mod schema_details;
4544
mod server;
4645
mod server_binary;

src/tests/krate/following.rs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@ use crate::builders::CrateBuilder;
22
use crate::util::{RequestHelper, TestApp};
33
use crate::OkBool;
44

5-
#[test]
6-
fn diesel_not_found_results_in_404() {
7-
let (_, _, user) = TestApp::init().with_user();
8-
9-
user.get("/api/v1/crates/foo_following/following")
10-
.assert_not_found();
11-
}
12-
135
#[test]
146
fn following() {
157
// TODO: Test anon requests as well?
@@ -58,23 +50,6 @@ fn following() {
5850
assert_eq!(user.search("following=1").crates.len(), 0);
5951
}
6052

61-
#[test]
62-
fn disallow_api_token_auth_for_get_crate_following_status() {
63-
let (app, _, _, token) = TestApp::init().with_token();
64-
let api_token = token.as_model();
65-
66-
let a_crate = "a_crate";
67-
68-
app.db(|conn| {
69-
CrateBuilder::new(a_crate, api_token.user_id).expect_build(conn);
70-
});
71-
72-
// Token auth on GET for get following status is disallowed
73-
token
74-
.get(&format!("/api/v1/crates/{a_crate}/following"))
75-
.assert_forbidden();
76-
}
77-
7853
#[test]
7954
fn getting_followed_crates_allows_api_token_auth() {
8055
let (app, _, user, token) = TestApp::init().with_token();

src/tests/krate/mod.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,4 @@
1-
mod dependencies;
2-
mod downloads;
31
mod following;
4-
mod owners;
52
mod publish;
6-
mod reverse_dependencies;
7-
mod search;
8-
mod show;
9-
mod summary;
103
mod versions;
114
mod yanking;

src/tests/krate/publish.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ fn new_with_underscore_renamed_dependency() {
197197

198198
#[test]
199199
fn new_krate_with_dependency() {
200-
use super::dependencies::Deps;
200+
use crate::routes::crates::versions::dependencies::Deps;
201201

202202
let (app, anon, user, token) = TestApp::full().with_token();
203203

src/tests/pagination.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use crate::builders::CrateBuilder;
2+
use crate::util::{RequestHelper, TestApp};
3+
use http::status::StatusCode;
4+
use ipnetwork::IpNetwork;
5+
use serde_json::json;
6+
7+
#[test]
8+
fn pagination_blocks_ip_from_cidr_block_list() {
9+
let (app, anon, user) = TestApp::init()
10+
.with_config(|config| {
11+
config.max_allowed_page_offset = 1;
12+
config.page_offset_cidr_blocklist = vec!["127.0.0.1/24".parse::<IpNetwork>().unwrap()];
13+
})
14+
.with_user();
15+
let user = user.as_model();
16+
17+
app.db(|conn| {
18+
CrateBuilder::new("pagination_links_1", user.id).expect_build(conn);
19+
CrateBuilder::new("pagination_links_2", user.id).expect_build(conn);
20+
CrateBuilder::new("pagination_links_3", user.id).expect_build(conn);
21+
});
22+
23+
let response = anon.get_with_query::<()>("/api/v1/crates", "page=2&per_page=1");
24+
assert_eq!(response.status(), StatusCode::BAD_REQUEST);
25+
assert_eq!(
26+
response.into_json(),
27+
json!({ "errors": [{ "detail": "requested page offset is too large" }] })
28+
);
29+
}

src/tests/category.rs renamed to src/tests/routes/categories/get.rs

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,10 @@
1-
use crate::util::insta::assert_yaml_snapshot;
2-
use crate::{
3-
builders::CrateBuilder, new_category, util::MockAnonymousUser, RequestHelper, TestApp,
4-
};
1+
use crate::builders::CrateBuilder;
2+
use crate::new_category;
3+
use crate::util::{MockAnonymousUser, RequestHelper, TestApp};
54
use cargo_registry::models::Category;
5+
use insta::assert_yaml_snapshot;
66
use serde_json::Value;
77

8-
#[test]
9-
fn index() {
10-
let (app, anon) = TestApp::init().empty();
11-
12-
// List 0 categories if none exist
13-
let json: Value = anon.get("/api/v1/categories").good();
14-
assert_yaml_snapshot!(json);
15-
16-
// Create a category and a subcategory
17-
app.db(|conn| {
18-
new_category("foo", "foo", "Foo crates")
19-
.create_or_update(conn)
20-
.unwrap();
21-
new_category("foo::bar", "foo::bar", "Bar crates")
22-
.create_or_update(conn)
23-
.unwrap();
24-
});
25-
26-
// Only the top-level categories should be on the page
27-
let json: Value = anon.get("/api/v1/categories").good();
28-
assert_yaml_snapshot!(json, {
29-
".categories[].created_at" => "[datetime]",
30-
});
31-
}
32-
338
#[test]
349
fn show() {
3510
let (app, anon) = TestApp::init().empty();
@@ -129,19 +104,3 @@ fn update_crate() {
129104
assert_eq!(count(&anon, "category-2"), 0);
130105
});
131106
}
132-
133-
#[test]
134-
fn category_slugs_returns_all_slugs_in_alphabetical_order() {
135-
let (app, anon) = TestApp::init().empty();
136-
app.db(|conn| {
137-
new_category("Foo", "foo", "For crates that foo")
138-
.create_or_update(conn)
139-
.unwrap();
140-
new_category("Bar", "bar", "For crates that bar")
141-
.create_or_update(conn)
142-
.unwrap();
143-
});
144-
145-
let response: Value = anon.get("/api/v1/category_slugs").good();
146-
assert_yaml_snapshot!(response);
147-
}

src/tests/routes/categories/list.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use crate::new_category;
2+
use crate::util::{RequestHelper, TestApp};
3+
use insta::assert_yaml_snapshot;
4+
use serde_json::Value;
5+
6+
#[test]
7+
fn index() {
8+
let (app, anon) = TestApp::init().empty();
9+
10+
// List 0 categories if none exist
11+
let json: Value = anon.get("/api/v1/categories").good();
12+
assert_yaml_snapshot!(json);
13+
14+
// Create a category and a subcategory
15+
app.db(|conn| {
16+
new_category("foo", "foo", "Foo crates")
17+
.create_or_update(conn)
18+
.unwrap();
19+
new_category("foo::bar", "foo::bar", "Bar crates")
20+
.create_or_update(conn)
21+
.unwrap();
22+
});
23+
24+
// Only the top-level categories should be on the page
25+
let json: Value = anon.get("/api/v1/categories").good();
26+
assert_yaml_snapshot!(json, {
27+
".categories[].created_at" => "[datetime]",
28+
});
29+
}

src/tests/routes/categories/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub mod get;
2+
pub mod list;

src/tests/snapshots/all__category__show.snap renamed to src/tests/routes/categories/snapshots/all__routes__categories__get__show.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
source: src/tests/category.rs
3-
assertion_line: 51
2+
source: src/tests/routes/categories/get.rs
3+
assertion_line: 26
44
expression: json
55
---
66
category:

src/tests/snapshots/all__category__index-2.snap renamed to src/tests/routes/categories/snapshots/all__routes__categories__list__index-2.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
source: src/tests/category.rs
3-
assertion_line: 33
2+
source: src/tests/routes/categories/list.rs
3+
assertion_line: 26
44
expression: json
55
---
66
categories:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: src/tests/routes/categories/list.rs
3+
assertion_line: 12
4+
expression: json
5+
---
6+
categories: []
7+
meta:
8+
total: 0
9+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use crate::new_category;
2+
use crate::util::{RequestHelper, TestApp};
3+
use insta::assert_yaml_snapshot;
4+
use serde_json::Value;
5+
6+
#[test]
7+
fn category_slugs_returns_all_slugs_in_alphabetical_order() {
8+
let (app, anon) = TestApp::init().empty();
9+
app.db(|conn| {
10+
new_category("Foo", "foo", "For crates that foo")
11+
.create_or_update(conn)
12+
.unwrap();
13+
new_category("Bar", "bar", "For crates that bar")
14+
.create_or_update(conn)
15+
.unwrap();
16+
});
17+
18+
let response: Value = anon.get("/api/v1/category_slugs").good();
19+
assert_yaml_snapshot!(response);
20+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod list;

src/tests/snapshots/all__category__category_slugs_returns_all_slugs_in_alphabetical_order.snap renamed to src/tests/routes/category_slugs/snapshots/all__routes__category_slugs__list__category_slugs_returns_all_slugs_in_alphabetical_order.snap

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
2-
source: src/tests/category.rs
3-
assertion_line: 153
2+
source: src/tests/routes/category_slugs/list.rs
3+
assertion_line: 19
44
expression: response
55
---
66
category_slugs:

src/tests/routes/crates/downloads.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use crate::builders::{CrateBuilder, VersionBuilder};
2+
use crate::util::{MockAnonymousUser, RequestHelper, TestApp};
3+
use cargo_registry::views::EncodableVersionDownload;
4+
use chrono::{Duration, Utc};
5+
use http::StatusCode;
6+
7+
#[derive(Deserialize)]
8+
struct Downloads {
9+
version_downloads: Vec<EncodableVersionDownload>,
10+
}
11+
12+
pub fn persist_downloads_count(app: &TestApp) {
13+
app.as_inner()
14+
.downloads_counter
15+
.persist_all_shards(app.as_inner())
16+
.expect("failed to persist downloads count")
17+
.log();
18+
}
19+
20+
#[track_caller]
21+
pub fn assert_dl_count(
22+
anon: &MockAnonymousUser,
23+
name_and_version: &str,
24+
query: Option<&str>,
25+
count: i32,
26+
) {
27+
let url = format!("/api/v1/crates/{name_and_version}/downloads");
28+
let downloads: Downloads = if let Some(query) = query {
29+
anon.get_with_query(&url, query).good()
30+
} else {
31+
anon.get(&url).good()
32+
};
33+
let total_downloads = downloads
34+
.version_downloads
35+
.iter()
36+
.map(|vd| vd.downloads)
37+
.sum::<i32>();
38+
assert_eq!(total_downloads, count);
39+
}
40+
41+
#[test]
42+
fn download() {
43+
let (app, anon, user) = TestApp::init().with_user();
44+
let user = user.as_model();
45+
46+
app.db(|conn| {
47+
CrateBuilder::new("foo_download", user.id)
48+
.version(VersionBuilder::new("1.0.0"))
49+
.expect_build(conn);
50+
});
51+
52+
let download = |name_and_version: &str| {
53+
let url = format!("/api/v1/crates/{name_and_version}/download");
54+
let response = anon.get::<()>(&url);
55+
assert_eq!(response.status(), StatusCode::FOUND);
56+
// TODO: test the with_json code path
57+
};
58+
59+
download("foo_download/1.0.0");
60+
// No downloads are counted until the counters are persisted
61+
assert_dl_count(&anon, "foo_download/1.0.0", None, 0);
62+
assert_dl_count(&anon, "foo_download", None, 0);
63+
persist_downloads_count(&app);
64+
// Now that the counters are persisted the download counts show up.
65+
assert_dl_count(&anon, "foo_download/1.0.0", None, 1);
66+
assert_dl_count(&anon, "foo_download", None, 1);
67+
68+
download("FOO_DOWNLOAD/1.0.0");
69+
persist_downloads_count(&app);
70+
assert_dl_count(&anon, "FOO_DOWNLOAD/1.0.0", None, 2);
71+
assert_dl_count(&anon, "FOO_DOWNLOAD", None, 2);
72+
73+
let yesterday = (Utc::now().date_naive() + Duration::days(-1)).format("%F");
74+
let query = format!("before_date={yesterday}");
75+
assert_dl_count(&anon, "FOO_DOWNLOAD/1.0.0", Some(&query), 0);
76+
// crate/downloads always returns the last 90 days and ignores date params
77+
assert_dl_count(&anon, "FOO_DOWNLOAD", Some(&query), 2);
78+
79+
let tomorrow = (Utc::now().date_naive() + Duration::days(1)).format("%F");
80+
let query = format!("before_date={tomorrow}");
81+
assert_dl_count(&anon, "FOO_DOWNLOAD/1.0.0", Some(&query), 2);
82+
assert_dl_count(&anon, "FOO_DOWNLOAD", Some(&query), 2);
83+
}

src/tests/routes/crates/following.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use crate::builders::CrateBuilder;
2+
use crate::util::{RequestHelper, TestApp};
3+
4+
#[test]
5+
fn diesel_not_found_results_in_404() {
6+
let (_, _, user) = TestApp::init().with_user();
7+
8+
user.get("/api/v1/crates/foo_following/following")
9+
.assert_not_found();
10+
}
11+
12+
#[test]
13+
fn disallow_api_token_auth_for_get_crate_following_status() {
14+
let (app, _, _, token) = TestApp::init().with_token();
15+
let api_token = token.as_model();
16+
17+
let a_crate = "a_crate";
18+
19+
app.db(|conn| {
20+
CrateBuilder::new(a_crate, api_token.user_id).expect_build(conn);
21+
});
22+
23+
// Token auth on GET for get following status is disallowed
24+
token
25+
.get(&format!("/api/v1/crates/{a_crate}/following"))
26+
.assert_forbidden();
27+
}

0 commit comments

Comments
 (0)