@@ -4,12 +4,13 @@ use std::collections::HashMap;
4
4
use std:: io:: prelude:: * ;
5
5
use std:: fs:: { self , File } ;
6
6
7
+ use chrono:: Utc ;
7
8
use conduit:: { Handler , Method } ;
8
-
9
- use git2;
9
+ use diesel:: update;
10
10
use self :: diesel:: prelude:: * ;
11
- use serde_json ;
11
+ use git2 ;
12
12
use semver;
13
+ use serde_json;
13
14
14
15
use cargo_registry:: dependency:: EncodableDependency ;
15
16
use cargo_registry:: download:: EncodableVersionDownload ;
@@ -18,11 +19,11 @@ use cargo_registry::keyword::EncodableKeyword;
18
19
use cargo_registry:: krate:: { Crate , EncodableCrate , MAX_NAME_LENGTH } ;
19
20
20
21
use cargo_registry:: token:: ApiToken ;
21
- use cargo_registry:: schema:: { crates, versions} ;
22
+ use cargo_registry:: schema:: { crates, metadata , versions} ;
22
23
23
24
use cargo_registry:: upload as u;
24
25
use cargo_registry:: version:: EncodableVersion ;
25
- use cargo_registry:: category:: Category ;
26
+ use cargo_registry:: category:: { Category , EncodableCategory } ;
26
27
27
28
use { CrateList , CrateMeta , GoodCrate } ;
28
29
@@ -51,6 +52,18 @@ struct Downloads {
51
52
version_downloads : Vec < EncodableVersionDownload > ,
52
53
}
53
54
55
+ #[ derive( Deserialize ) ]
56
+ struct SummaryResponse {
57
+ num_downloads : i64 ,
58
+ num_crates : i64 ,
59
+ new_crates : Vec < EncodableCrate > ,
60
+ most_downloaded : Vec < EncodableCrate > ,
61
+ most_recently_downloaded : Vec < EncodableCrate > ,
62
+ just_updated : Vec < EncodableCrate > ,
63
+ popular_keywords : Vec < EncodableKeyword > ,
64
+ popular_categories : Vec < EncodableCategory > ,
65
+ }
66
+
54
67
fn new_crate ( name : & str ) -> u:: NewCrate {
55
68
u:: NewCrate {
56
69
name : u:: CrateName ( name. to_string ( ) ) ,
@@ -984,6 +997,80 @@ fn summary_doesnt_die() {
984
997
ok_resp ! ( middle. call( & mut req) ) ;
985
998
}
986
999
1000
+ #[ test]
1001
+ fn summary_new_crates ( ) {
1002
+ let ( _b, app, middle) = :: app ( ) ;
1003
+ let u;
1004
+ let krate;
1005
+ let krate2;
1006
+ let krate3;
1007
+ {
1008
+ let conn = app. diesel_database . get ( ) . unwrap ( ) ;
1009
+ u = :: new_user ( "foo" ) . create_or_update ( & conn) . unwrap ( ) ;
1010
+
1011
+ krate = :: CrateBuilder :: new ( "some_downloads" , u. id )
1012
+ . version ( :: VersionBuilder :: new ( "0.1.0" ) )
1013
+ . description ( "description" )
1014
+ . keyword ( "popular" )
1015
+ . downloads ( 20 )
1016
+ . recent_downloads ( 10 )
1017
+ . expect_build ( & conn) ;
1018
+
1019
+ krate2 = :: CrateBuilder :: new ( "most_recent_downloads" , u. id )
1020
+ . version ( :: VersionBuilder :: new ( "0.2.0" ) )
1021
+ . keyword ( "popular" )
1022
+ . downloads ( 5000 )
1023
+ . recent_downloads ( 50 )
1024
+ . expect_build ( & conn) ;
1025
+
1026
+ krate3 = :: CrateBuilder :: new ( "just_updated" , u. id )
1027
+ . version ( :: VersionBuilder :: new ( "0.1.0" ) )
1028
+ . expect_build ( & conn) ;
1029
+
1030
+ :: CrateBuilder :: new ( "with_downloads" , u. id )
1031
+ . version ( :: VersionBuilder :: new ( "0.3.0" ) )
1032
+ . keyword ( "popular" )
1033
+ . downloads ( 1000 )
1034
+ . expect_build ( & conn) ;
1035
+
1036
+ :: new_category ( "Category 1" , "cat1" )
1037
+ . create_or_update ( & conn)
1038
+ . unwrap ( ) ;
1039
+ Category :: update_crate ( & conn, & krate, & [ "cat1" ] ) . unwrap ( ) ;
1040
+ Category :: update_crate ( & conn, & krate2, & [ "cat1" ] ) . unwrap ( ) ;
1041
+
1042
+ // set total_downloads global value for `num_downloads` prop
1043
+ update ( metadata:: table)
1044
+ . set ( metadata:: total_downloads. eq ( 6000 ) )
1045
+ . execute ( & * conn)
1046
+ . unwrap ( ) ;
1047
+
1048
+ // update 'just_updated' krate. Others won't appear because updated_at == created_at.
1049
+ let updated = Utc :: now ( ) . naive_utc ( ) ;
1050
+ update ( & krate3)
1051
+ . set ( crates:: updated_at. eq ( updated) )
1052
+ . execute ( & * conn)
1053
+ . unwrap ( ) ;
1054
+ }
1055
+
1056
+ let mut req = :: req ( app. clone ( ) , Method :: Get , "/api/v1/summary" ) ;
1057
+ let mut response = ok_resp ! ( middle. call( & mut req) ) ;
1058
+ let json: SummaryResponse = :: json ( & mut response) ;
1059
+
1060
+ assert_eq ! ( json. num_crates, 4 ) ;
1061
+ assert_eq ! ( json. num_downloads, 6000 ) ;
1062
+ assert_eq ! ( json. most_downloaded[ 0 ] . name, "most_recent_downloads" ) ;
1063
+ assert_eq ! (
1064
+ json. most_recently_downloaded[ 0 ] . name,
1065
+ "most_recent_downloads"
1066
+ ) ;
1067
+ assert_eq ! ( json. popular_keywords[ 0 ] . keyword, "popular" ) ;
1068
+ assert_eq ! ( json. popular_categories[ 0 ] . category, "Category 1" ) ;
1069
+ assert_eq ! ( json. just_updated. len( ) , 1 ) ;
1070
+ assert_eq ! ( json. just_updated[ 0 ] . name, "just_updated" ) ;
1071
+ assert_eq ! ( json. new_crates. len( ) , 4 ) ;
1072
+ }
1073
+
987
1074
#[ test]
988
1075
fn download ( ) {
989
1076
use chrono:: { Duration , Utc } ;
0 commit comments