From e7a3609eeca32c696f306f4290fe64eba6f0d980 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sat, 30 Nov 2019 07:32:51 -0500 Subject: [PATCH 01/17] Sketch testing newest_version --- src/tests/krate.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 82815951f77..aede9191cc2 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -1243,6 +1243,13 @@ fn summary_new_crates() { let krate3 = CrateBuilder::new("just_updated", user.id) .version(VersionBuilder::new("0.1.0")) + .version(VersionBuilder::new("0.1.2")) + .expect_build(conn); + + let krate4 = CrateBuilder::new("just_updated_patch", user.id) + .version(VersionBuilder::new("0.1.0")) + .version(VersionBuilder::new("0.2.0")) + .version(VersionBuilder::new("0.1.1")) .expect_build(conn); CrateBuilder::new("with_downloads", user.id) @@ -1269,11 +1276,19 @@ fn summary_new_crates() { .set(crates::updated_at.eq(updated)) .execute(&*conn) .unwrap(); + + // Adjust 'just_updated_patch' to be a little newer than 'just_updated' + update(&krate4) + .set(crates::updated_at.eq(updated + chrono::Duration::seconds(2))) + .execute(&*conn) + .unwrap(); + + // TODO: Make sure that the most recently updated version for just_updated_patch is 0.1.1. }); let json: SummaryResponse = anon.get("/api/v1/summary").good(); - assert_eq!(json.num_crates, 4); + assert_eq!(json.num_crates, 5); assert_eq!(json.num_downloads, 6000); assert_eq!(json.most_downloaded[0].name, "most_recent_downloads"); assert_eq!( @@ -1282,9 +1297,17 @@ fn summary_new_crates() { ); assert_eq!(json.popular_keywords[0].keyword, "popular"); assert_eq!(json.popular_categories[0].category, "Category 1"); - assert_eq!(json.just_updated.len(), 1); - assert_eq!(json.just_updated[0].name, "just_updated"); - assert_eq!(json.new_crates.len(), 4); + assert_eq!(json.just_updated.len(), 2); + + assert_eq!(json.just_updated[0].name, "just_updated_patch"); + assert_eq!(json.just_updated[0].max_version, "0.2.0"); + // TODO: assert_eq!(json.just_updated[0].newest_version, "0.1.1"); + + assert_eq!(json.just_updated[1].name, "just_updated"); + assert_eq!(json.just_updated[1].max_version, "0.1.2"); + // TODO: assert_eq!(json.just_updated[1].newest_version, "0.1.2"); + + assert_eq!(json.new_crates.len(), 5); } #[test] From 592f61228d988209b913e9f5362b3af9a9f1c024 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sat, 30 Nov 2019 07:55:03 -0500 Subject: [PATCH 02/17] Add newest field --- src/models/krate.rs | 1 + src/tests/krate.rs | 4 ++-- src/views.rs | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/models/krate.rs b/src/models/krate.rs index a6839b19e92..e339b267892 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -340,6 +340,7 @@ impl Crate { categories: category_ids, badges, max_version: max_version.to_string(), + newest_version: max_version.to_string(), // FIXME: Make this the newest, not the highest documentation, homepage, exact_match, diff --git a/src/tests/krate.rs b/src/tests/krate.rs index aede9191cc2..9d1abd4ca61 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -1301,11 +1301,11 @@ fn summary_new_crates() { assert_eq!(json.just_updated[0].name, "just_updated_patch"); assert_eq!(json.just_updated[0].max_version, "0.2.0"); - // TODO: assert_eq!(json.just_updated[0].newest_version, "0.1.1"); + // FIXME: assert_eq!(json.just_updated[0].newest_version, "0.1.1"); assert_eq!(json.just_updated[1].name, "just_updated"); assert_eq!(json.just_updated[1].max_version, "0.1.2"); - // TODO: assert_eq!(json.just_updated[1].newest_version, "0.1.2"); + assert_eq!(json.just_updated[1].newest_version, "0.1.2"); assert_eq!(json.new_crates.len(), 5); } diff --git a/src/views.rs b/src/views.rs index 981578e8be7..e5b86a8f98b 100644 --- a/src/views.rs +++ b/src/views.rs @@ -97,6 +97,7 @@ pub struct EncodableCrate { pub recent_downloads: Option, // NOTE: Used by shields.io, altering `max_version` requires a PR with shields.io pub max_version: String, + pub newest_version: String, // Most recently updated version, which may not be max pub description: Option, pub homepage: Option, pub documentation: Option, @@ -363,6 +364,7 @@ mod tests { downloads: 0, recent_downloads: None, max_version: "".to_string(), + newest_version: "".to_string(), description: None, homepage: None, documentation: None, From f65a6409535836688e9ddd81a5897ab51cc77da0 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sat, 30 Nov 2019 14:58:29 -0500 Subject: [PATCH 03/17] TopVersions for highest and newest --- src/controllers/krate/metadata.rs | 6 ++-- src/controllers/krate/publish.rs | 4 +-- src/controllers/krate/search.rs | 2 +- src/models/krate.rs | 49 +++++++++++++++++++++++-------- src/tests/util.rs | 2 +- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/controllers/krate/metadata.rs b/src/controllers/krate/metadata.rs index 14e42c2c533..7b049e179ec 100644 --- a/src/controllers/krate/metadata.rs +++ b/src/controllers/krate/metadata.rs @@ -31,7 +31,7 @@ pub fn summary(req: &mut dyn Request) -> AppResult { versions .grouped_by(&krates) .into_iter() - .map(|versions| Version::max(versions.into_iter().map(|v| v.num))) + .map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string()) .zip(krates) .map(|(max_version, krate)| { Ok(krate.minimal_encodable(&max_version, None, false, None)) @@ -142,7 +142,7 @@ pub fn show(req: &mut dyn Request) -> AppResult { let badges = badges::table .filter(badges::crate_id.eq(krate.id)) .load(&*conn)?; - let max_version = krate.max_version(&conn)?; + let top_versions = krate.top_versions(&conn)?; #[derive(Serialize)] struct R { @@ -154,7 +154,7 @@ pub fn show(req: &mut dyn Request) -> AppResult { } Ok(req.json(&R { krate: krate.clone().encodable( - &max_version, + &top_versions, Some(ids), Some(&kws), Some(&cats), diff --git a/src/controllers/krate/publish.rs b/src/controllers/krate/publish.rs index 09dce9934aa..91b67f3afb7 100644 --- a/src/controllers/krate/publish.rs +++ b/src/controllers/krate/publish.rs @@ -168,7 +168,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult { // Update all badges for this crate, collecting any invalid badges in // order to be able to warn about them let ignored_invalid_badges = Badge::update_crate(&conn, &krate, new_crate.badges.as_ref())?; - let max_version = krate.max_version(&conn)?; + let top_versions = krate.top_versions(&conn)?; if let Some(readme) = new_crate.readme { render::render_and_upload_readme( @@ -215,7 +215,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult { }; Ok(req.json(&GoodCrate { - krate: krate.minimal_encodable(&max_version, None, false, None), + krate: krate.minimal_encodable(&top_versions.highest, None, false, None), warnings, })) }) diff --git a/src/controllers/krate/search.rs b/src/controllers/krate/search.rs index 2ad799bd4ce..772d0493d49 100644 --- a/src/controllers/krate/search.rs +++ b/src/controllers/krate/search.rs @@ -179,7 +179,7 @@ pub fn search(req: &mut dyn Request) -> AppResult { .load::(&*conn)? .grouped_by(&crates) .into_iter() - .map(|versions| Version::max(versions.into_iter().map(|v| v.num))); + .map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string()); let badges = CrateBadge::belonging_to(&crates) .select((badges::crate_id, badges::all_columns)) diff --git a/src/models/krate.rs b/src/models/krate.rs index e339b267892..c048936ff6b 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -48,6 +48,14 @@ pub struct Crate { pub max_upload_size: Option, } +/// The highest version (in semver order) and the most recently updated version +/// for a single crate. +#[derive(Debug, Clone)] +pub struct TopVersions { + pub highest: String, + pub newest: String, +} + /// We literally never want to select `textsearchable_index_col` /// so we provide this type and constant to pass to `.select` type AllColumns = ( @@ -204,7 +212,7 @@ impl<'a> NewCrate<'a> { } impl Crate { - /// SQL filter based on whether the crate's name loosly matches the given + /// SQL filter based on whether the crate's name loosely matches the given /// string. /// /// The operator used varies based on the input. @@ -281,13 +289,16 @@ impl Crate { pub fn minimal_encodable( self, - max_version: &semver::Version, + max_version: &str, badges: Option>, exact_match: bool, recent_downloads: Option, ) -> EncodableCrate { self.encodable( - max_version, + &TopVersions { + highest: max_version.to_owned(), + newest: max_version.to_owned(), + }, None, None, None, @@ -300,7 +311,7 @@ impl Crate { #[allow(clippy::too_many_arguments)] pub fn encodable( self, - max_version: &semver::Version, + top_versions: &TopVersions, versions: Option>, keywords: Option<&[Keyword]>, categories: Option<&[Category]>, @@ -339,8 +350,8 @@ impl Crate { keywords: keyword_ids, categories: category_ids, badges, - max_version: max_version.to_string(), - newest_version: max_version.to_string(), // FIXME: Make this the newest, not the highest + max_version: top_versions.highest.to_owned(), + newest_version: top_versions.newest.to_owned(), documentation, homepage, exact_match, @@ -385,16 +396,28 @@ impl Crate { } } - pub fn max_version(&self, conn: &PgConnection) -> AppResult { + pub fn top_versions(&self, conn: &PgConnection) -> AppResult { use crate::schema::versions::dsl::*; - let vs = self + let results = self .versions() - .select(num) - .load::(conn)? - .into_iter() - .map(|s| semver::Version::parse(&s).unwrap()); - Ok(Version::max(vs)) + .select((updated_at, num)) + .load::<(NaiveDateTime, String)>(conn)?; + + Ok(TopVersions { + newest: results + .to_owned() + .into_iter() + .max() + .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) + .1, + highest: Version::max( + results + .into_iter() + .map(|(_, s)| semver::Version::parse(&s).unwrap()), + ) + .to_string(), + }) } pub fn owners(&self, conn: &PgConnection) -> AppResult> { diff --git a/src/tests/util.rs b/src/tests/util.rs index 054a44d92da..76b2e8b180b 100644 --- a/src/tests/util.rs +++ b/src/tests/util.rs @@ -305,7 +305,7 @@ impl TestAppBuilder { } } -/// A colleciton of helper methods for the 3 authentication types +/// A collection of helper methods for the 3 authentication types /// /// Helper methods go through public APIs, and should not modify the database directly pub trait RequestHelper { From 4d92475e52ebc2fab6fd75dabaa6d9c5c4536b0f Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sat, 30 Nov 2019 20:46:30 -0500 Subject: [PATCH 04/17] Doc for top_versions function --- src/models/krate.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/models/krate.rs b/src/models/krate.rs index c048936ff6b..325b1ddbb60 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -396,6 +396,8 @@ impl Crate { } } + /// Return both the newest (most recently updated) and + /// highest version (in semver order) for the current crate. pub fn top_versions(&self, conn: &PgConnection) -> AppResult { use crate::schema::versions::dsl::*; From ec7a166bb1f53817a774c969cb57296072861ac8 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sat, 30 Nov 2019 23:22:26 -0500 Subject: [PATCH 05/17] Deal with TopVersions everywhere This contains far too much repeated code. It does basically work and the relevant test passes! I'll refactor the redundant code into a shared function. --- src/controllers/krate/metadata.rs | 27 ++++++++++++++++++++++++--- src/controllers/krate/publish.rs | 2 +- src/controllers/krate/search.rs | 23 ++++++++++++++++++++++- src/models/krate.rs | 7 ++----- src/tests/krate.rs | 17 +++++++++++------ 5 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/controllers/krate/metadata.rs b/src/controllers/krate/metadata.rs index 7b049e179ec..2ecf14c2eed 100644 --- a/src/controllers/krate/metadata.rs +++ b/src/controllers/krate/metadata.rs @@ -5,6 +5,8 @@ //! `Cargo.toml` file. use crate::controllers::frontend_prelude::*; +use chrono::NaiveDateTime; + use crate::models::{ Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads, User, Version, VersionOwnerAction, @@ -31,10 +33,29 @@ pub fn summary(req: &mut dyn Request) -> AppResult { versions .grouped_by(&krates) .into_iter() - .map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string()) + .map(|versions| { + let pairs: Vec<_> = versions + .into_iter() + .map(|version| (version.created_at, version.num.to_string())) + .collect(); + TopVersions { + newest: pairs + .to_owned() + .into_iter() + .max() + .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) + .1, + highest: Version::max( + pairs + .into_iter() + .map(|(_, s)| semver::Version::parse(&s).unwrap()), + ) + .to_string(), + } + }) .zip(krates) - .map(|(max_version, krate)| { - Ok(krate.minimal_encodable(&max_version, None, false, None)) + .map(|(top_versions, krate)| { + Ok(krate.minimal_encodable(&top_versions, None, false, None)) }) .collect() }; diff --git a/src/controllers/krate/publish.rs b/src/controllers/krate/publish.rs index 91b67f3afb7..b3d93a9f672 100644 --- a/src/controllers/krate/publish.rs +++ b/src/controllers/krate/publish.rs @@ -215,7 +215,7 @@ pub fn publish(req: &mut dyn Request) -> AppResult { }; Ok(req.json(&GoodCrate { - krate: krate.minimal_encodable(&top_versions.highest, None, false, None), + krate: krate.minimal_encodable(&top_versions, None, false, None), warnings, })) }) diff --git a/src/controllers/krate/search.rs b/src/controllers/krate/search.rs index 772d0493d49..498c1614ccc 100644 --- a/src/controllers/krate/search.rs +++ b/src/controllers/krate/search.rs @@ -1,10 +1,12 @@ //! Endpoint for searching and discovery functionality +use chrono::NaiveDateTime; use diesel::dsl::*; use diesel_full_text_search::*; use crate::controllers::cargo_prelude::*; use crate::controllers::helpers::Paginate; +use crate::models::krate::TopVersions; use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version}; use crate::schema::*; use crate::views::EncodableCrate; @@ -179,7 +181,26 @@ pub fn search(req: &mut dyn Request) -> AppResult { .load::(&*conn)? .grouped_by(&crates) .into_iter() - .map(|versions| Version::max(versions.into_iter().map(|v| v.num)).to_string()); + .map(|versions| { + let pairs: Vec<_> = versions + .into_iter() + .map(|version| (version.created_at, version.num.to_string())) + .collect(); + TopVersions { + newest: pairs + .to_owned() + .into_iter() + .max() + .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) + .1, + highest: Version::max( + pairs + .into_iter() + .map(|(_, s)| semver::Version::parse(&s).unwrap()), + ) + .to_string(), + } + }); let badges = CrateBadge::belonging_to(&crates) .select((badges::crate_id, badges::all_columns)) diff --git a/src/models/krate.rs b/src/models/krate.rs index 325b1ddbb60..10d866d1913 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -289,16 +289,13 @@ impl Crate { pub fn minimal_encodable( self, - max_version: &str, + top_versions: &TopVersions, badges: Option>, exact_match: bool, recent_downloads: Option, ) -> EncodableCrate { self.encodable( - &TopVersions { - highest: max_version.to_owned(), - newest: max_version.to_owned(), - }, + top_versions, None, None, None, diff --git a/src/tests/krate.rs b/src/tests/krate.rs index 9d1abd4ca61..f85912dc487 100644 --- a/src/tests/krate.rs +++ b/src/tests/krate.rs @@ -1249,7 +1249,6 @@ fn summary_new_crates() { let krate4 = CrateBuilder::new("just_updated_patch", user.id) .version(VersionBuilder::new("0.1.0")) .version(VersionBuilder::new("0.2.0")) - .version(VersionBuilder::new("0.1.1")) .expect_build(conn); CrateBuilder::new("with_downloads", user.id) @@ -1277,13 +1276,19 @@ fn summary_new_crates() { .execute(&*conn) .unwrap(); - // Adjust 'just_updated_patch' to be a little newer than 'just_updated' - update(&krate4) - .set(crates::updated_at.eq(updated + chrono::Duration::seconds(2))) + let plus_two = Utc::now().naive_utc() + chrono::Duration::seconds(2); + let newer = VersionBuilder::new("0.1.1").expect_build(krate4.id, user.id, conn); + + // Update the patch version to be newer than the other versions, including the higher one. + update(&newer) + .set(versions::created_at.eq(plus_two)) .execute(&*conn) .unwrap(); - // TODO: Make sure that the most recently updated version for just_updated_patch is 0.1.1. + update(&krate4) + .set(crates::updated_at.eq(plus_two)) + .execute(&*conn) + .unwrap(); }); let json: SummaryResponse = anon.get("/api/v1/summary").good(); @@ -1301,7 +1306,7 @@ fn summary_new_crates() { assert_eq!(json.just_updated[0].name, "just_updated_patch"); assert_eq!(json.just_updated[0].max_version, "0.2.0"); - // FIXME: assert_eq!(json.just_updated[0].newest_version, "0.1.1"); + assert_eq!(json.just_updated[0].newest_version, "0.1.1"); assert_eq!(json.just_updated[1].name, "just_updated"); assert_eq!(json.just_updated[1].max_version, "0.1.2"); From 55af1d1d02f43911047a008ad894266c9da30f16 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sun, 1 Dec 2019 10:12:49 -0500 Subject: [PATCH 06/17] Refactor top_version into the version module Where we used to have max_version, we now have two kinds of top versions: - the highest semver version - the most recently updated version. --- src/controllers/krate/metadata.rs | 24 ++------------- src/controllers/krate/search.rs | 23 +------------- src/models/krate.rs | 40 ++++++------------------ src/models/version.rs | 51 +++++++++++++++++++++++-------- 4 files changed, 51 insertions(+), 87 deletions(-) diff --git a/src/controllers/krate/metadata.rs b/src/controllers/krate/metadata.rs index 2ecf14c2eed..2817ebf9c54 100644 --- a/src/controllers/krate/metadata.rs +++ b/src/controllers/krate/metadata.rs @@ -1,11 +1,10 @@ //! Endpoints that expose metadata about a crate //! -//! These endpoints provide data that could be obtained direclty from the +//! These endpoints provide data that could be obtained directly from the //! index or cached metadata which was extracted (client side) from the //! `Cargo.toml` file. use crate::controllers::frontend_prelude::*; -use chrono::NaiveDateTime; use crate::models::{ Category, Crate, CrateCategory, CrateKeyword, CrateVersions, Keyword, RecentCrateDownloads, @@ -33,26 +32,7 @@ pub fn summary(req: &mut dyn Request) -> AppResult { versions .grouped_by(&krates) .into_iter() - .map(|versions| { - let pairs: Vec<_> = versions - .into_iter() - .map(|version| (version.created_at, version.num.to_string())) - .collect(); - TopVersions { - newest: pairs - .to_owned() - .into_iter() - .max() - .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) - .1, - highest: Version::max( - pairs - .into_iter() - .map(|(_, s)| semver::Version::parse(&s).unwrap()), - ) - .to_string(), - } - }) + .map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num)))) .zip(krates) .map(|(top_versions, krate)| { Ok(krate.minimal_encodable(&top_versions, None, false, None)) diff --git a/src/controllers/krate/search.rs b/src/controllers/krate/search.rs index 498c1614ccc..05aaa6c9bc1 100644 --- a/src/controllers/krate/search.rs +++ b/src/controllers/krate/search.rs @@ -1,12 +1,10 @@ //! Endpoint for searching and discovery functionality -use chrono::NaiveDateTime; use diesel::dsl::*; use diesel_full_text_search::*; use crate::controllers::cargo_prelude::*; use crate::controllers::helpers::Paginate; -use crate::models::krate::TopVersions; use crate::models::{Crate, CrateBadge, CrateOwner, CrateVersions, OwnerKind, Version}; use crate::schema::*; use crate::views::EncodableCrate; @@ -181,26 +179,7 @@ pub fn search(req: &mut dyn Request) -> AppResult { .load::(&*conn)? .grouped_by(&crates) .into_iter() - .map(|versions| { - let pairs: Vec<_> = versions - .into_iter() - .map(|version| (version.created_at, version.num.to_string())) - .collect(); - TopVersions { - newest: pairs - .to_owned() - .into_iter() - .max() - .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) - .1, - highest: Version::max( - pairs - .into_iter() - .map(|(_, s)| semver::Version::parse(&s).unwrap()), - ) - .to_string(), - } - }); + .map(|versions| Version::top(versions.into_iter().map(|v| (v.created_at, v.num)))); let badges = CrateBadge::belonging_to(&crates) .select((badges::crate_id, badges::all_columns)) diff --git a/src/models/krate.rs b/src/models/krate.rs index 10d866d1913..46d035a4dae 100644 --- a/src/models/krate.rs +++ b/src/models/krate.rs @@ -8,12 +8,12 @@ use url::Url; use crate::app::App; use crate::email; -use crate::util::{cargo_err, AppResult}; - +use crate::models::version::TopVersions; use crate::models::{ Badge, Category, CrateOwner, CrateOwnerInvitation, Keyword, NewCrateOwnerInvitation, Owner, OwnerKind, ReverseDependency, User, Version, }; +use crate::util::{cargo_err, AppResult}; use crate::views::{EncodableCrate, EncodableCrateLinks}; use crate::models::helpers::with_count::*; @@ -48,14 +48,6 @@ pub struct Crate { pub max_upload_size: Option, } -/// The highest version (in semver order) and the most recently updated version -/// for a single crate. -#[derive(Debug, Clone)] -pub struct TopVersions { - pub highest: String, - pub newest: String, -} - /// We literally never want to select `textsearchable_index_col` /// so we provide this type and constant to pass to `.select` type AllColumns = ( @@ -347,8 +339,8 @@ impl Crate { keywords: keyword_ids, categories: category_ids, badges, - max_version: top_versions.highest.to_owned(), - newest_version: top_versions.newest.to_owned(), + max_version: top_versions.highest.to_string(), + newest_version: top_versions.newest.to_string(), documentation, homepage, exact_match, @@ -398,25 +390,11 @@ impl Crate { pub fn top_versions(&self, conn: &PgConnection) -> AppResult { use crate::schema::versions::dsl::*; - let results = self - .versions() - .select((updated_at, num)) - .load::<(NaiveDateTime, String)>(conn)?; - - Ok(TopVersions { - newest: results - .to_owned() - .into_iter() - .max() - .unwrap_or((NaiveDateTime::from_timestamp(0, 0), "0.0.0".to_owned())) - .1, - highest: Version::max( - results - .into_iter() - .map(|(_, s)| semver::Version::parse(&s).unwrap()), - ) - .to_string(), - }) + Ok(Version::top( + self.versions() + .select((updated_at, num)) + .load::<(NaiveDateTime, semver::Version)>(conn)?, + )) } pub fn owners(&self, conn: &PgConnection) -> AppResult> { diff --git a/src/models/version.rs b/src/models/version.rs index 0ee71275d64..54345f746ff 100644 --- a/src/models/version.rs +++ b/src/models/version.rs @@ -37,6 +37,25 @@ pub struct NewVersion { published_by: i32, } +/// The highest version (semver order) and the most recently updated version. +/// Typically used for a single crate. +#[derive(Debug, Clone)] +pub struct TopVersions { + pub highest: semver::Version, + pub newest: semver::Version, +} + +/// A default semver value, "0.0.0", for use in TopVersions +fn default_semver_version() -> semver::Version { + semver::Version { + major: 0, + minor: 0, + patch: 0, + pre: vec![], + build: vec![], + } +} + impl Version { pub fn encodable( self, @@ -96,20 +115,28 @@ impl Version { .load(conn) } - pub fn max(versions: T) -> semver::Version + /// Return both the newest (most recently updated) and the + /// highest version (in semver order) for a collection of date/version pairs. + pub fn top(pairs: T) -> TopVersions where - T: IntoIterator, + T: Clone + IntoIterator, { - versions - .into_iter() - .max() - .unwrap_or_else(|| semver::Version { - major: 0, - minor: 0, - patch: 0, - pre: vec![], - build: vec![], - }) + TopVersions { + newest: pairs + .clone() + .into_iter() + .max() + .unwrap_or(( + NaiveDateTime::from_timestamp(0, 0), + default_semver_version(), + )) + .1, + highest: pairs + .into_iter() + .map(|(_, v)| v) + .max() + .unwrap_or_else(default_semver_version), + } } pub fn record_readme_rendering(version_id_: i32, conn: &PgConnection) -> QueryResult { From 0b373d70d390e1e91e8dca8b2694d905f90a11d6 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Mon, 2 Dec 2019 19:51:51 -0500 Subject: [PATCH 07/17] Fancy handling of crate versions on home page - For the Just Updated column, the newest version is displayed - For the Most Downloaded column, no version is displayed - For the New Crates column, the highest version is displayed (unchanged) --- .../{crate-list.hbs => crate-list-max.hbs} | 0 app/templates/components/crate-list-name-only.hbs | 12 ++++++++++++ app/templates/components/crate-list-newest.hbs | 12 ++++++++++++ app/templates/index.hbs | 8 ++++---- tests/acceptance/front-page-test.js | 2 +- 5 files changed, 29 insertions(+), 5 deletions(-) rename app/templates/components/{crate-list.hbs => crate-list-max.hbs} (100%) create mode 100644 app/templates/components/crate-list-name-only.hbs create mode 100644 app/templates/components/crate-list-newest.hbs diff --git a/app/templates/components/crate-list.hbs b/app/templates/components/crate-list-max.hbs similarity index 100% rename from app/templates/components/crate-list.hbs rename to app/templates/components/crate-list-max.hbs diff --git a/app/templates/components/crate-list-name-only.hbs b/app/templates/components/crate-list-name-only.hbs new file mode 100644 index 00000000000..66e7039f90f --- /dev/null +++ b/app/templates/components/crate-list-name-only.hbs @@ -0,0 +1,12 @@ +
    + {{#each crates as |crate index|}} +
  1. + {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} + {{ crate.name }} +
    + {{svg-jar "right-arrow"}} +
    + {{/link-to}} +
  2. + {{/each}} +
diff --git a/app/templates/components/crate-list-newest.hbs b/app/templates/components/crate-list-newest.hbs new file mode 100644 index 00000000000..ee0574c6038 --- /dev/null +++ b/app/templates/components/crate-list-newest.hbs @@ -0,0 +1,12 @@ +
    + {{#each crates as |crate index|}} +
  1. + {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} + {{ crate.name }} ({{ crate.newest_version }}) +
    + {{svg-jar "right-arrow"}} +
    + {{/link-to}} +
  2. + {{/each}} +
diff --git a/app/templates/index.hbs b/app/templates/index.hbs index 9a32236f93b..4b6e4d401a3 100644 --- a/app/templates/index.hbs +++ b/app/templates/index.hbs @@ -38,19 +38,19 @@

New Crates

- +

Most Downloaded

- +

Just Updated

- +

Most Recent Downloads

- +

Popular Keywords (see all)

diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index f31eeb9a0b5..afe52f23b89 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -38,7 +38,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); - assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde (0.6.1)'); + assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.7.0-alpha)'); From 797fce03fc12719292de765c5d54b43e7936d23f Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Mon, 2 Dec 2019 20:16:29 -0500 Subject: [PATCH 08/17] Set nanomsg-0.6.1 as newest, not highest --- mirage/fixtures/versions.js | 4 ++-- tests/acceptance/front-page-test.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/mirage/fixtures/versions.js b/mirage/fixtures/versions.js index 5a6a7347ed1..e7aaa14bd6f 100644 --- a/mirage/fixtures/versions.js +++ b/mirage/fixtures/versions.js @@ -1,7 +1,7 @@ export default [ { crate: 'nanomsg', - created_at: '2016-12-27T08:40:00Z', + created_at: '2016-12-20T07:30:00Z', dl_path: '/api/v1/crates/nanomsg/0.7.0-alpha.1/download', downloads: 260, features: { @@ -9,7 +9,7 @@ export default [ }, id: 40906, num: '0.7.0-alpha.1', - updated_at: '2016-12-27T08:40:00Z', + updated_at: '2016-12-20T07:30:00Z', yanked: false, license: 'MIT', crate_size: 912355, diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index afe52f23b89..4e381146afa 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -41,7 +41,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); - assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.7.0-alpha)'); + assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.6.1)'); assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasAttribute('href', '/crates/nanomsg'); percySnapshot(assert); From 8df106195eafaff38a59179bc40ef7c2489d6de7 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Mon, 2 Dec 2019 20:46:47 -0500 Subject: [PATCH 09/17] Add newest_version to each crate fixture --- mirage/fixtures/crates.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/mirage/fixtures/crates.js b/mirage/fixtures/crates.js index be295dacba3..8ec46073fa6 100644 --- a/mirage/fixtures/crates.js +++ b/mirage/fixtures/crates.js @@ -17,6 +17,7 @@ export default [ id: 'kinetic-rust', keywords: ['Protocol', 'Kinetic', 'Storage'], max_version: '0.0.16', + newest_version: '0.0.16', name: 'kinetic-rust', repository: 'https://github.com/icorderi/kinetic-rust/', updated_at: '2015-04-21T00:15:49Z', @@ -41,6 +42,7 @@ export default [ id: 'nanomsg', keywords: ['network'], max_version: '0.7.0-alpha', + newest_version: '0.6.1', name: 'nanomsg', repository: 'https://github.com/thehydroimpulse/nanomsg.rs', updated_at: '2016-12-28T08:40:00Z', @@ -70,6 +72,7 @@ export default [ id: 'rust_mixin', keywords: ['rust', 'plugin', 'code-generation'], max_version: '0.0.1', + newest_version: '0.0.1', name: 'rust_mixin', repository: 'https://github.com/huonw/external_mixin', updated_at: '2015-02-27T11:52:13Z', @@ -142,6 +145,7 @@ export default [ id: 'external_mixin', keywords: ['python', 'ruby', 'shell', 'plugin', 'code-generation'], max_version: '0.0.1', + newest_version: '0.0.1', name: 'external_mixin', repository: 'https://github.com/huonw/external_mixin', updated_at: '2015-02-27T11:51:58Z', @@ -157,6 +161,7 @@ export default [ id: 'external_mixin_umbrella', keywords: ['plugin', 'code-generation'], max_version: '0.0.2', + newest_version: '0.0.2', name: 'external_mixin_umbrella', repository: 'https://github.com/huonw/external_mixin', updated_at: '2015-02-27T11:52:30Z', @@ -173,6 +178,7 @@ export default [ id: 'Inflector', keywords: ['string', 'case', 'camel', 'snake', 'inflection'], max_version: '0.1.6', + newest_version: '0.1.6', name: 'Inflector', repository: 'https://github.com/whatisinternet/inflector', updated_at: '2015-10-27T01:51:42Z', @@ -188,6 +194,7 @@ export default [ id: 'rs-es', keywords: ['elasticsearch', 'elastic'], max_version: '0.1.17', + newest_version: '0.1.17', name: 'rs-es', repository: 'https://github.com/benashford/rs-es', updated_at: '2015-09-09T15:34:50Z', @@ -203,6 +210,7 @@ export default [ id: 'rust-crypto', keywords: ['Crypto', 'MD5', 'Sha1', 'Sha2', 'AES'], max_version: '0.2.34', + newest_version: '0.2.34', name: 'rust-crypto', repository: 'https://github.com/DaGenix/rust-crypto/', updated_at: '2015-10-29T01:16:17Z', @@ -218,6 +226,7 @@ export default [ id: 'rust-htslib', keywords: ['htslib', 'bam', 'bioinformatics', 'pileup', 'sequencing'], max_version: '0.5.2', + newest_version: '0.5.2', name: 'rust-htslib', repository: 'https://github.com/rust-bio/rust-htslib.git', updated_at: '2015-11-11T00:10:43Z', @@ -233,6 +242,7 @@ export default [ id: 'rustless', keywords: ['api', 'web', 'hyper', 'iron', 'rest'], max_version: '0.8.0', + newest_version: '0.8.0', name: 'rustless', repository: 'https://crates.io/crates/rustless', updated_at: '2015-10-31T11:49:29Z', @@ -248,6 +258,7 @@ export default [ id: 'serde', keywords: ['serde', 'serialization'], max_version: '0.6.1', + newest_version: '0.6.1', name: 'serde', repository: 'https://github.com/serde-rs/serde', updated_at: '2015-10-18T03:10:21Z', @@ -263,6 +274,7 @@ export default [ id: 'rusted_cypher', keywords: ['neo4j', 'database', 'query', 'cypher', 'graph'], max_version: '0.7.1', + newest_version: '0.7.1', name: 'rusted_cypher', repository: 'https://github.com/livioribeiro/rusted-cypher', updated_at: '2015-11-07T17:26:55Z', @@ -279,6 +291,7 @@ export default [ id: 'zlib', keywords: [], max_version: '0.0.1', + newest_version: '0.0.1', name: 'zlib', repository: null, updated_at: '2015-01-02T20:54:04Z', @@ -295,6 +308,7 @@ export default [ id: 'rustful', keywords: ['web', 'rest', 'framework', 'http', 'routing'], max_version: '0.5.0', + newest_version: '0.5.0', name: 'rustful', repository: 'https://github.com/Ogeon/rustful', updated_at: '2015-09-19T21:10:27Z', @@ -310,6 +324,7 @@ export default [ id: 'postgres', keywords: ['database', 'sql'], max_version: '0.10.1', + newest_version: '0.10.1', name: 'postgres', repository: 'https://github.com/sfackler/rust-postgres', updated_at: '2015-11-08T00:48:59Z', @@ -325,6 +340,7 @@ export default [ id: 'quickcheck', keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], max_version: '0.2.24', + newest_version: '0.2.24', name: 'quickcheck', repository: 'https://github.com/BurntSushi/quickcheck', updated_at: '2015-09-20T21:53:38Z', @@ -340,6 +356,7 @@ export default [ id: 'quickcheck_macros', keywords: ['testing', 'quickcheck', 'property', 'shrinking', 'fuzz'], max_version: '0.2.24', + newest_version: '0.2.24', name: 'quickcheck_macros', repository: 'https://github.com/BurntSushi/quickcheck', updated_at: '2015-09-20T21:53:57Z', @@ -356,6 +373,7 @@ export default [ id: 'nc_rustlex', keywords: ['lexer', 'lexical', 'analyser', 'generator'], max_version: '0.3.1', + newest_version: '0.3.1', name: 'nc_rustlex', repository: 'https://github.com/nicolas-cherel/rustlex', updated_at: '2015-08-25T19:15:35Z', @@ -371,6 +389,7 @@ export default [ id: 'nom', keywords: ['parser', 'parser-combinators', 'parsing', 'streaming', 'bit'], max_version: '1.0.1', + newest_version: '1.0.1', name: 'nom', repository: 'https://github.com/Geal/nom', updated_at: '2015-11-22T22:00:41Z', From d02aeb9e7dc514de6d4803436aa068d55c144f16 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Tue, 3 Dec 2019 09:09:47 -0500 Subject: [PATCH 10/17] Add newest_version placeholders --- app/models/crate.js | 1 + mirage/factories/crate.js | 1 + mirage/serializers/crate.js | 1 + 3 files changed, 3 insertions(+) diff --git a/app/models/crate.js b/app/models/crate.js index 59cbf21bf24..f7401510a73 100644 --- a/app/models/crate.js +++ b/app/models/crate.js @@ -8,6 +8,7 @@ export default Model.extend({ created_at: attr('date'), updated_at: attr('date'), max_version: attr('string'), + newest_version: attr('string'), description: attr('string'), homepage: attr('string'), diff --git a/mirage/factories/crate.js b/mirage/factories/crate.js index f354a1d5aa5..899f2a0dd02 100644 --- a/mirage/factories/crate.js +++ b/mirage/factories/crate.js @@ -16,6 +16,7 @@ export default Factory.extend({ homepage: () => faker.internet.url(), repository: () => faker.internet.url(), max_version: () => faker.system.semver(), + newest_version: () => faker.system.semver(), created_at: () => faker.date.past(), updated_at() { diff --git a/mirage/serializers/crate.js b/mirage/serializers/crate.js index 940a8f3d27e..ef9ad34957c 100644 --- a/mirage/serializers/crate.js +++ b/mirage/serializers/crate.js @@ -14,6 +14,7 @@ export default BaseSerializer.extend({ 'keywords', 'links', 'max_version', + 'newest_version', 'name', 'repository', 'updated_at', From 759a920a12ef0f59df849c2c134c80a8d2f06c8a Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Wed, 4 Dec 2019 20:07:08 -0500 Subject: [PATCH 11/17] For "Just Updated" link to the specific version --- app/templates/components/crate-list-newest.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/templates/components/crate-list-newest.hbs b/app/templates/components/crate-list-newest.hbs index ee0574c6038..4254ac452c0 100644 --- a/app/templates/components/crate-list-newest.hbs +++ b/app/templates/components/crate-list-newest.hbs @@ -1,7 +1,7 @@
    {{#each crates as |crate index|}}
  1. - {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} + {{#link-to 'crate.version' crate.id crate.newest_version class='name' data-test-crate-link=index}} {{ crate.name }} ({{ crate.newest_version }})
    {{svg-jar "right-arrow"}} From 2e085bf995e65ef72965b9e7b9a8565f6b3561a3 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Wed, 4 Dec 2019 20:15:55 -0500 Subject: [PATCH 12/17] Adjust tests for versioned "Just Updated" links --- tests/acceptance/crate-test.js | 2 +- tests/acceptance/front-page-test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/crate-test.js b/tests/acceptance/crate-test.js index 3bab3e97591..9d0541f5840 100644 --- a/tests/acceptance/crate-test.js +++ b/tests/acceptance/crate-test.js @@ -66,7 +66,7 @@ module('Acceptance | crate page', function(hooks) { await visit('/'); await click('[data-test-just-updated] [data-test-crate-link="0"]'); - assert.equal(currentURL(), '/crates/nanomsg'); + assert.equal(currentURL(), '/crates/nanomsg/6.8.9'); assert.equal(title(), 'nanomsg - crates.io: Rust Package Registry'); }); diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index 4e381146afa..78695599feb 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -42,7 +42,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasText('nanomsg (0.6.1)'); - assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasAttribute('href', '/crates/nanomsg'); + assert.dom('[data-test-just-updated] [data-test-crate-link="0"]').hasAttribute('href', '/crates/nanomsg/0.6.1'); percySnapshot(assert); }); From 1b02232716537c88e0a8029ec882edf489aa1eec Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Thu, 5 Dec 2019 17:38:04 -0500 Subject: [PATCH 13/17] Even fewer crate versions on home page --- tests/acceptance/front-page-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index 78695599feb..6dc48e474af 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -35,7 +35,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-total-downloads]').hasText('122,669'); assert.dom('[data-test-total-crates]').hasText('19'); - assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); + assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector'); assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde'); From 79af4e43e33d4980cb924532d806ba412b115ac8 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Wed, 11 Dec 2019 06:59:06 -0500 Subject: [PATCH 14/17] For "New Crates" link to the specific version shown --- app/templates/components/crate-list-max.hbs | 12 ------------ tests/acceptance/front-page-test.js | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) delete mode 100644 app/templates/components/crate-list-max.hbs diff --git a/app/templates/components/crate-list-max.hbs b/app/templates/components/crate-list-max.hbs deleted file mode 100644 index f4c69d02739..00000000000 --- a/app/templates/components/crate-list-max.hbs +++ /dev/null @@ -1,12 +0,0 @@ -
      - {{#each this.crates as |crate index|}} -
    1. - - {{ crate.name }} ({{ crate.max_version }}) -
      - {{svg-jar "right-arrow"}} -
      -
      -
    2. - {{/each}} -
    diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index 6dc48e474af..78695599feb 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -35,7 +35,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-total-downloads]').hasText('122,669'); assert.dom('[data-test-total-crates]').hasText('19'); - assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector'); + assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde'); From 66f9ab6fdea0807df97269fcee303fb6db300627 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Wed, 11 Dec 2019 07:18:11 -0500 Subject: [PATCH 15/17] Finish reverting the "New Crates" test for version --- tests/acceptance/front-page-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/acceptance/front-page-test.js b/tests/acceptance/front-page-test.js index 78695599feb..8fc023b87b0 100644 --- a/tests/acceptance/front-page-test.js +++ b/tests/acceptance/front-page-test.js @@ -36,7 +36,7 @@ module('Acceptance | front page', function(hooks) { assert.dom('[data-test-total-crates]').hasText('19'); assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasText('Inflector (0.1.6)'); - assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector'); + assert.dom('[data-test-new-crates] [data-test-crate-link="0"]').hasAttribute('href', '/crates/Inflector/0.1.6'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasText('serde'); assert.dom('[data-test-most-downloaded] [data-test-crate-link="0"]').hasAttribute('href', '/crates/serde'); From 77f08494c53c05f2c82388e100adc21df8d9c6b6 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Sun, 22 Dec 2019 08:18:01 -0500 Subject: [PATCH 16/17] Narrow test fixtures in single test --- tests/acceptance/crate-test.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/crate-test.js b/tests/acceptance/crate-test.js index 9d0541f5840..2d4561be7a4 100644 --- a/tests/acceptance/crate-test.js +++ b/tests/acceptance/crate-test.js @@ -61,13 +61,17 @@ module('Acceptance | crate page', function(hooks) { }); test('visiting a crate page from the front page', async function(assert) { - this.server.create('crate', 'withVersion', { id: 'nanomsg' }); + this.server.create('crate', { id: 'nanomsg', newest_version: '0.6.1' }); + this.server.create('version', { crate: 'nanomsg', num: '0.6.1' }); await visit('/'); await click('[data-test-just-updated] [data-test-crate-link="0"]'); - assert.equal(currentURL(), '/crates/nanomsg/6.8.9'); + assert.equal(currentURL(), '/crates/nanomsg/0.6.1'); assert.equal(title(), 'nanomsg - crates.io: Rust Package Registry'); + + assert.dom('[data-test-heading] [data-test-crate-name]').hasText('nanomsg'); + assert.dom('[data-test-heading] [data-test-crate-version]').hasText('0.6.1'); }); test('visiting /crates/nanomsg', async function(assert) { From fb356c4194684ff204d41a4a9e50551b6f77ace9 Mon Sep 17 00:00:00 2001 From: Bruce Adams Date: Mon, 23 Dec 2019 08:57:11 -0500 Subject: [PATCH 17/17] Repair `LinkTo` and `this.` missed during rebase --- app/templates/components/crate-list-name-only.hbs | 6 +++--- app/templates/components/crate-list-newest.hbs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/templates/components/crate-list-name-only.hbs b/app/templates/components/crate-list-name-only.hbs index 66e7039f90f..63be00ae384 100644 --- a/app/templates/components/crate-list-name-only.hbs +++ b/app/templates/components/crate-list-name-only.hbs @@ -1,12 +1,12 @@
      - {{#each crates as |crate index|}} + {{#each this.crates as |crate index|}}
    1. - {{#link-to 'crate' crate.id class='name' data-test-crate-link=index}} + {{ crate.name }}
      {{svg-jar "right-arrow"}}
      - {{/link-to}} +
    2. {{/each}}
    diff --git a/app/templates/components/crate-list-newest.hbs b/app/templates/components/crate-list-newest.hbs index 4254ac452c0..39a7659743e 100644 --- a/app/templates/components/crate-list-newest.hbs +++ b/app/templates/components/crate-list-newest.hbs @@ -1,12 +1,12 @@
      - {{#each crates as |crate index|}} + {{#each this.crates as |crate index|}}
    1. - {{#link-to 'crate.version' crate.id crate.newest_version class='name' data-test-crate-link=index}} + {{ crate.name }} ({{ crate.newest_version }})
      {{svg-jar "right-arrow"}}
      - {{/link-to}} +
    2. {{/each}}