From 6c628d24de3b0df5feea36de95b03cff9d863b93 Mon Sep 17 00:00:00 2001 From: Tait Hoyem Date: Wed, 19 Apr 2023 16:33:37 -0600 Subject: [PATCH] Update other methods to use new db connections --- Cargo.lock | 33 ++++++++- Cargo.toml | 2 + src/languages.rs | 45 +++++++++++- src/main.rs | 77 +++++++++++++++----- src/model.rs | 186 ++++++++++++++++++++++++++++++++++++++++------- src/views.rs | 88 +++++++++++++++++++--- 6 files changed, 372 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1171941..40e6e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -383,6 +383,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -525,7 +534,7 @@ version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", + "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", @@ -1123,6 +1132,8 @@ dependencies = [ "lazy_static", "once_cell", "ormx", + "rename", + "rename-item", "rust-embed", "rust-i18n", "serde", @@ -1724,6 +1735,26 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "rename" +version = "0.1.1" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rename-item" +version = "0.1.0" +dependencies = [ + "convert_case 0.6.0", + "darling", + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ring" version = "0.16.20" diff --git a/Cargo.toml b/Cargo.toml index 850b49c..9a15af2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,8 @@ i18n-embed-fl = "0.6.6" rust-embed = { version = "6.6.1", features = ["axum"] } lazy_static = "1.4.0" ibihf-macros = { version = "0.1.0", path = "ibihf-macros" } +rename = { version = "0.1.1", path = "../rename-rs" } +rename-item = { version = "0.1.0", path = "../rename-item" } [dev-dependencies] tokio-test = "0.4.2" diff --git a/src/languages.rs b/src/languages.rs index c606eb3..edb761d 100644 --- a/src/languages.rs +++ b/src/languages.rs @@ -9,11 +9,13 @@ use strum_macros::{AsRefStr, EnumCount, EnumIter, EnumVariantNames}; use derive_more::Display; #[derive( + sqlx::Type, Serialize, Deserialize, Clone, Copy, Debug, + Hash, Display, EnumIter, EnumCount, @@ -22,13 +24,22 @@ use derive_more::Display; PartialEq, Eq, )] +#[repr(i32)] pub enum SupportedLanguage { #[serde(rename = "en-ca")] #[display(fmt = "en-ca")] - English, + English = 1, #[serde(rename = "fr-ca")] #[display(fmt = "fr-ca")] - French, + French = 2, +} +impl Into for SupportedLanguage { + fn into(self) -> i32 { + match self { + Self::English => 1, + Self::French => 2, + } + } } impl From for FluentValue<'_> { fn from(n: SupportedLanguage) -> Self { @@ -64,6 +75,12 @@ impl SupportedLanguage { } .to_string() } + pub fn id(&self) -> i32 { + match self { + Self::English => 1, + Self::French => 2, + } + } } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -71,3 +88,27 @@ pub struct LangLink { pub href: String, pub name: String, } + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct LocalizedName { + pub localizations: std::collections::HashMap, +} +impl LocalizedName { + fn localize(&self, lang: SupportedLanguage) -> Option { + // first, try to find the proper match for a name + self.localizations + .iter() + .find_map(|(translated_lang, string)| if translated_lang == &lang { + Some(string.to_string()) + } else { + None + }) + // if not found, replace it with ANY localization of the word; this will help when, for example, there is no matching name for a French game, but the game has already been created with the English name. + // if NO localization is found, then we can still return a None value; but hopefully through database, form, and web server restrictions, we can mostly stop that from happening + .or_else(|| if self.localizations.len() >= 1 { + Some(self.localizations.values().nth(0).unwrap().to_string()) + } else { + None + }) + } +} diff --git a/src/main.rs b/src/main.rs index afb3a83..1cf1db4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ macro_rules! other_lang_urls { } }).collect() }; - ($lang:expr, $template:ident, $($k:literal => $v:expr),+) => { + ($lang:expr, $template:ident, $($k:literal => $v:expr),*) => { $lang.other_langs().map(move |olang| { LangLink { name: olang.native_name(), @@ -30,7 +30,7 @@ macro_rules! other_lang_urls { $template::URL_KEY_TEMPLATE, hashmap_macro::hashmap![ "lang" => olang.to_string().into(), - $($k => $v.into()),+ + $($k => $v.into()),* ], ) .expect("Unable to find key {key} in locale {self}.") @@ -38,6 +38,38 @@ macro_rules! other_lang_urls { }).collect() }; } +macro_rules! impl_url_gen { + ($struct:ident, $($name:ident: $ty:ty),*) => { + impl $struct<'_> { + #[allow(dead_code)] + fn lang_link(lang: SupportedLanguage, $($name: $ty),*) -> LangLink { + LangLink { + name: lang.native_name(), + href: Into::::into(lang) + .translate( + Self::URL_KEY_TEMPLATE, + hashmap_macro::hashmap![ + "lang" => lang.into(), + $(stringify!($name) => $name.into()),* + ], + ) + .expect("Unable to find key {key} in locale {self}.") + } + } + } + #[cfg(test)] + #[rename_item::rename(case="snake")] + #[rename::rename_mod(prepend="test_")] + mod $struct { + use crate::SupportedLanguage; + use crate::$struct; + #[test] + fn test_lang_link_types() { + println!("{:?}", $struct::lang_link(SupportedLanguage::English, 0)); + } + } + } +} use static_assertions::assert_impl_all; use traits::TemplateUrl; @@ -110,6 +142,7 @@ struct DivisionListTemplate<'a> { divisions: Vec, lang: SupportedLanguage, } +impl_url_gen!(DivisionListTemplate, id: i32); assert_impl_all!(DivisionListTemplate: TemplateUrl); #[derive(Template, TemplateUrl)] @@ -122,6 +155,7 @@ struct LeagueListTemplate<'a> { lang: SupportedLanguage, leagues: Vec, } +impl_url_gen!(LeagueListTemplate, id: i32); assert_impl_all!(LeagueListTemplate: TemplateUrl); #[derive(Template)] @@ -144,6 +178,7 @@ struct GameListTemplate<'a> { games: Vec, lang: SupportedLanguage, } +impl_url_gen!(GameListTemplate, id: i32); assert_impl_all!(GameListTemplate: TemplateUrl); #[derive(Template)] @@ -169,6 +204,7 @@ struct GameScorePageTemplate<'a> { play_by_play: ShotsTableTemplate<'a>, lang: SupportedLanguage, } +impl_url_gen!(GameScorePageTemplate, id: i32); assert_impl_all!(GameScorePageTemplate: TemplateUrl); #[derive(Template, TemplateUrl)] @@ -208,15 +244,15 @@ async fn main() { &SupportedLanguage::English.lookup(GameListTemplate::URL_KEY), get(games_for_division_html), ) - .route( - &SupportedLanguage::English.lookup(GameScorePageTemplate::URL_KEY), - get(score_for_game_html), - ) - .route( - &SupportedLanguage::French.lookup(GameScorePageTemplate::URL_KEY), - get(score_for_game_html), - ) - .route("/:lang/player/:name/", get(player_from_name)) + //.route( + // &SupportedLanguage::English.lookup(GameScorePageTemplate::URL_KEY), + // get(score_for_game_html), + //) + //.route( + // &SupportedLanguage::French.lookup(GameScorePageTemplate::URL_KEY), + // get(score_for_game_html), + //) + //.route("/:lang/player/:name/", get(player_from_name)) .with_state(state); let addr = SocketAddr::from(([127, 0, 0, 1], 8000)); println!("Listening on {}", addr); @@ -297,7 +333,7 @@ async fn league_html( State(server_config): State, Path(lang): Path, ) -> impl IntoResponse { - let leagues = League::all(&*server_config.db_pool).await.unwrap(); + let leagues = League::all(&*server_config.db_pool, lang).await.unwrap(); let leagues_template = LeagueListTemplate { lang_links: other_lang_urls!(lang, LeagueListTemplate), locale: lang.into(), @@ -311,10 +347,11 @@ async fn divisions_for_league_html( State(server_config): State, Path((lang, league_id)): Path<(SupportedLanguage, i32)>, ) -> impl IntoResponse { - let league = League::get(&*server_config.db_pool, league_id) + let league = League::get(&*server_config.db_pool, league_id, lang.into()) .await + .unwrap() .unwrap(); - let divisions = Division::by_league(&*server_config.db_pool, league_id) + let divisions = Division::by_league(&*server_config.db_pool, league_id, lang) .await .unwrap(); let html = DivisionListTemplate { @@ -332,13 +369,14 @@ async fn games_for_division_html( State(server_config): State, Path((lang, division_id)): Path<(SupportedLanguage, i32)>, ) -> impl IntoResponse { - let division = Division::get(&*server_config.db_pool, division_id) + let division = Division::get(&*server_config.db_pool, division_id, lang) .await + .unwrap() .unwrap(); - let games = Game::by_division(&*server_config.db_pool, division.id) + let games = Game::by_division(&*server_config.db_pool, division.id, lang) .await .unwrap(); - let iihf_stats = division.iihf_stats(&*server_config.db_pool).await.unwrap(); + let iihf_stats = division.iihf_stats(&*server_config.db_pool, lang).await.unwrap(); let games_template = GameListTemplate { locale: lang.into(), lang_links: other_lang_urls!(lang, GameListTemplate, "id" => division_id), @@ -352,6 +390,7 @@ async fn games_for_division_html( }; (StatusCode::OK, games_template) } +/* async fn score_for_game_html( State(server_config): State, Path((lang, game_id)): Path<(SupportedLanguage, i32)>, @@ -361,8 +400,9 @@ async fn score_for_game_html( .fetch_one(&*server_config.db_pool) .await .unwrap(); - let division = Division::get(&*server_config.db_pool, game.division) + let division = Division::get(&*server_config.db_pool, game.division, lang) .await + .unwrap() .unwrap(); let pbp = game.play_by_play(&server_config.db_pool).await.unwrap(); let score = game.score(&server_config.db_pool).await.unwrap(); @@ -397,6 +437,7 @@ async fn score_for_game_html( }; (StatusCode::OK, game_template) } +*/ /* macro_rules! insert { diff --git a/src/model.rs b/src/model.rs index 57b7141..d401685 100644 --- a/src/model.rs +++ b/src/model.rs @@ -6,6 +6,10 @@ use sqlx::FromRow; pub trait TableName { const TABLE_NAME: &'static str; } +pub trait NameTableName { + const NAME_TABLE_NAME: &'static str; + const NAME_TABLE_FK_NAME: &'static str; +} macro_rules! impl_table_name { ($ty:ident, $tname:literal) => { impl TableName for $ty { @@ -13,6 +17,14 @@ macro_rules! impl_table_name { } }; } +macro_rules! impl_name_table_name { + ($ty:ident, $tname:literal, $fk_name:literal) => { + impl NameTableName for $ty { + const NAME_TABLE_NAME: &'static str = $tname; + const NAME_TABLE_FK_NAME: &'static str = $fk_name; + } + }; +} #[derive(FromRow, Serialize, Deserialize, Debug, ormx::Table)] #[ormx(table = "supported_languages", id = id, insertable, deletable)] @@ -23,59 +35,174 @@ pub struct Language { pub short_name: String, } -#[derive(FromRow, Serialize, Deserialize, Debug, ormx::Table)] -#[ormx(table = "leagues", id = id, insertable, deletable)] +macro_rules! impl_localized_get { + ($struct:ident, $func:ident) => { + impl $struct { + pub async fn get(pool: &sqlx::PgPool, id: i32, lang: crate::SupportedLanguage) -> Result, sqlx::Error> { + let query = const_format::formatcp!(r#" +SELECT + {0}.*, + {1}({0}.id, $2) AS name +FROM {0} +WHERE {0}.id = $1;"#, + stringify!(<$struct as TableName>::TABLE_NAME), + stringify!($func), + ); + sqlx::query_as::<_, $struct>(&query) + .bind(id) + .bind(lang) + .fetch_optional(pool) + .await + } + } + }; +} +macro_rules! impl_localized_get_by_many { + ($struct:ident, $by:ident) => { + impl $struct { + #[rename::rename_fn(prepend="by_")] + pub async fn $by(pool: &sqlx::PgPool, by: i32, lang: crate::SupportedLanguage) -> Result, sqlx::Error> { + let query = format!(r#" +SELECT + {0}.*, + -- if available, use the localized name, + -- if not, choose the default name (in English, CA) + -- if not, see if there is any name attached (there should be at least some language selected) + COALESCE( + localized_name.name, + default_name.name, + any_name.name + ) AS name +FROM {0} +-- search for the proper, localized name +LEFT JOIN {1} localized_name + ON localized_name.{2} = {0}.id + AND localized_name.language = $2 +-- also look for the name in the default language (English, CA) +LEFT JOIN {1} default_name + ON default_name.{2} = {0}.id + AND default_name.language=1 +-- also look for ANY matching name in ANY locale +LEFT JOIN {1} any_name + ON any_name.{2} = {0}.id +WHERE {0}.{3} = $1;"#, + <$struct as TableName>::TABLE_NAME, + <$struct as NameTableName>::NAME_TABLE_NAME, + <$struct as NameTableName>::NAME_TABLE_FK_NAME, + stringify!($by), + ); + sqlx::query_as::<_, $struct>(&query) + .bind(by) + .bind(lang) + .fetch_all(pool) + .await + } + } + }; +} +macro_rules! impl_localized_all { + ($struct:ident) => { + impl $struct { + pub async fn all(pool: &sqlx::PgPool, lang: crate::SupportedLanguage) -> Result, sqlx::Error> { + let query = format!(r#" +SELECT + {0}.*, + -- if available, use the localized name, + -- if not, choose the default name (in English, CA) + -- if not, see if there is any name attached (there should be at least some language selected) + COALESCE( + localized_name.name, + default_name.name, + any_name.name + ) AS name +FROM {0} +-- search for the proper, localized name +LEFT JOIN {1} localized_name + ON localized_name.{2} = {0}.id + AND localized_name.language = $1 +-- also look for the name in the default language (English, CA) +LEFT JOIN {1} default_name + ON default_name.{2} = {0}.id + AND default_name.language=1 +-- also look for ANY matching name in ANY locale +LEFT JOIN {1} any_name + ON any_name.{2} = {0}.id;"#, + <$struct as TableName>::TABLE_NAME, + <$struct as NameTableName>::NAME_TABLE_NAME, + <$struct as NameTableName>::NAME_TABLE_FK_NAME, + ); + sqlx::query_as::<_, $struct>(&query) + .bind(lang) + .fetch_all(pool) + .await + } + } + }; +} + +#[derive(FromRow, Serialize, Deserialize, Debug, NameTableName)] +#[table_names(table_name = "leagues", name_func = "league_name", name_table_name = "league_names", name_table_name_fk = "league")] pub struct League { - #[ormx(default)] + //#[ormx(default)] pub id: i32, - pub name: String, + pub name: Option, } +//impl_localized_get!(League, league_name); +impl_localized_all!(League); +/* #[derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch)] #[ormx(table_name = "leagues", table = League, id = "id")] pub struct NewLeague { - pub name: String, + pub name: String, } +*/ -#[derive(FromRow, Serialize, Deserialize, Debug, ormx::Table)] -#[ormx(table = "divisions", id = id, insertable, deletable)] +#[derive(FromRow, Serialize, Deserialize, Debug)] +//#[ormx(table = "divisions", id = id, insertable, deletable)] pub struct Division { - #[ormx(default)] + //#[ormx(default)] pub id: i32, - pub name: String, - #[ormx(get_many(i32))] + //#[ormx(get_many(i32))] pub league: i32, + pub name: Option, } +impl_localized_get!(Division, division_name); +impl_localized_get_by_many!(Division, league); +impl_localized_all!(Division); -#[derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch)] -#[ormx(table_name = "divisions", table = Division, id = "id")] +#[derive(FromRow, Serialize, Deserialize, Debug)] +//#[ormx(table_name = "divisions", table = Division, id = "id")] pub struct NewDivision { - pub name: String, pub league: i32, } -#[derive(FromRow, Serialize, Deserialize, Debug, ormx::Table)] -#[ormx(table = "teams", id = id, insertable, deletable)] +#[derive(FromRow, Serialize, Deserialize, Debug)] +//#[ormx(table = "teams", id = id, insertable, deletable)] pub struct Team { - #[ormx(default)] + //#[ormx(default)] pub id: i32, - pub name: String, pub division: i32, pub image: Option, + pub name: Option, } +impl_localized_get!(Team, team_name); +/* #[derive(FromRow, Serialize, Deserialize, Debug, ormx::Patch)] #[ormx(table_name = "teams", table = Team, id = "id")] pub struct NewTeam { pub name: String, pub division: i32, } +*/ #[derive(FromRow, Serialize, Deserialize, Debug, ormx::Table)] #[ormx(table = "players", id = id, insertable, deletable)] pub struct Player { - #[ormx(default)] + //#[ormx(default)] pub id: i32, - pub name: String, + pub first_names: String, + pub last_name: String, pub weight_kg: Option, pub height_cm: Option, } @@ -95,7 +222,8 @@ impl Player { #[derive(FromRow, Deserialize, Serialize, Debug, ormx::Patch)] #[ormx(table_name = "players", table = Player, id = "id")] pub struct NewPlayer { - pub name: String, + pub first_names: String, + pub last_name: String, pub weight_kg: Option, pub height_cm: Option, } @@ -130,17 +258,19 @@ pub struct GamePlayer { pub game: i32, } -#[derive(FromRow, Deserialize, Serialize, Debug, ormx::Table)] -#[ormx(table = "games", id = id, insertable, deletable)] +#[derive(FromRow, Deserialize, Serialize, Debug)] +//#[ormx(table = "games", id = id, insertable, deletable)] pub struct Game { - #[ormx(default)] + //#[ormx(default)] pub id: i32, - #[ormx(get_many(i32))] + //#[ormx(get_many(i32))] pub division: i32, - pub name: String, pub team_home: i32, pub team_away: i32, + pub name: Option, } +impl_localized_get!(Game, game_name); +impl_localized_get_by_many!(Game, division); #[derive(FromRow, Deserialize, Serialize, Debug, ormx::Table)] #[ormx(table = "periods", id = id, insertable, deletable)] @@ -154,10 +284,14 @@ pub struct Period { impl_table_name!(GamePlayer, "game_players"); impl_table_name!(Player, "players"); impl_table_name!(League, "leagues"); +//impl_name_table_name!(League, "league_names", "league"); impl_table_name!(Division, "divisions"); +impl_name_table_name!(Division, "division_names", "division"); impl_table_name!(Team, "teams"); +impl_name_table_name!(Team, "team_names", "team"); impl_table_name!(Shot, "shots"); impl_table_name!(Game, "games"); +impl_name_table_name!(Game, "game_names", "game"); impl_table_name!(Period, "periods"); impl_table_name!(Language, "supported_languages"); @@ -197,7 +331,7 @@ mod tests { let player = Player::from_name_case_insensitive(&pool, "tait-hoyem".to_string()).await; assert!(player.is_some()); let player = player.unwrap(); - assert_eq!(player.name, "Tait Hoyem"); + assert_eq!(player.first_names, "Tait"); }) } diff --git a/src/views.rs b/src/views.rs index 00c6019..373c52e 100644 --- a/src/views.rs +++ b/src/views.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use crate::model::{Division, Game, League, Player}; +use crate::languages::SupportedLanguage; use serde::{Deserialize, Serialize}; use sqlx::FromRow; use sqlx::PgPool; @@ -280,9 +281,32 @@ impl Game { pub async fn division_iihf_stats( pool: &PgPool, division_id: i32, + lang: SupportedLanguage, ) -> Result, sqlx::Error> { sqlx::query_as::<_, IihfStatsI64>( r#" +WITH team_name AS ( + SELECT + teams.id AS team_id, + -- max will get the first matching string; technically it will always get the string that that has the maximum value based on the locale, ignoring nulls. + COALESCE( + MAX(localized_name.name), + MAX(default_name.name), + MAX(any_name.name) + ) AS team_name, + -- this is to get the language id of the team name; although not strictly necessary, since we use MIN(...), then ORDER BY it later on, we prioritize languages that have been added earlier, making this table deterministic + COALESCE( + MIN(localized_name.language), + MIN(default_name.language), + MIN(any_name.language) + ) AS name_language + FROM teams + LEFT JOIN team_names localized_name ON localized_name.team = teams.id AND localized_name.language = $2 + LEFT JOIN team_names default_name ON default_name.team = teams.id AND default_name.language = 1 + LEFT JOIN team_names any_name ON any_name.team = teams.id + GROUP BY teams.id + ORDER BY name_language +) SELECT SUM(reg_win(games.id, teams.id)) AS reg_wins, SUM(reg_loss(games.id, teams.id)) AS reg_losses, @@ -291,25 +315,62 @@ SELECT SUM(tie(games.id, teams.id)) AS ties, SUM(iihf_points(games.id, teams.id)) AS points, teams.id AS team_id, - teams.name AS team_name + team_name.team_name FROM games JOIN teams ON teams.id=games.team_home OR teams.id=games.team_away +JOIN team_name ON team_name.team_id=teams.id WHERE games.division=$1 GROUP BY - teams.id + teams.id, + team_name.team_name ORDER BY points DESC; + +--SELECT DISTINCT ON (teams.id) +-- SUM(reg_win(games.id, teams.id)) AS reg_wins, +-- SUM(reg_loss(games.id, teams.id)) AS reg_losses, +-- SUM(ot_win(games.id, teams.id)) AS ot_wins, +-- SUM(ot_loss(games.id, teams.id)) AS ot_losses, +-- SUM(tie(games.id, teams.id)) AS ties, +-- SUM(iihf_points(games.id, teams.id)) AS points, +-- teams.id AS team_id, +-- COALESCE( +-- localized_name.name, +-- default_name.name, +-- any_name.name +-- ) AS team_name +--FROM +-- games +--JOIN teams ON teams.id=games.team_home OR teams.id=games.team_away +--LEFT JOIN team_names localized_name +-- ON localized_name.team = teams.id +-- AND localized_name.language = $2 +--LEFT JOIN team_names default_name +-- ON default_name.team = teams.id +-- AND default_name.language = 1 +--LEFT JOIN team_names any_name +-- ON any_name.team = teams.id +--WHERE games.division=$1 +--GROUP BY +-- teams.id, +-- localized_name.name, +-- default_name.name, +-- any_name.name +--ORDER BY +-- teams.id, +-- points DESC; "#, ) .bind(division_id) + .bind(lang) .fetch_all(pool) .await } impl Division { - pub async fn iihf_stats(&self, pool: &PgPool) -> Result, sqlx::Error> { - division_iihf_stats(pool, self.id).await + pub async fn iihf_stats(&self, pool: &PgPool, lang: SupportedLanguage) -> Result, sqlx::Error> { + division_iihf_stats(pool, self.id, lang).await } } @@ -506,6 +567,7 @@ pub struct ShotDetails { #[cfg(test)] mod tests { + use crate::languages::SupportedLanguage; use crate::model::{Game, League, Player}; use crate::views::{ division_iihf_stats, game_box_score, game_goals, game_iihf_points, game_iihf_stats, @@ -535,7 +597,7 @@ mod tests { fn check_league_player_stats() { tokio_test::block_on(async move { let pool = db_connect().await; - let league = League::get(&pool, 1).await.unwrap(); + let league = League::get(&pool, 1, SupportedLanguage::English).await.unwrap().unwrap(); let player = Player::get(&pool, 2).await.unwrap(); let stats = League::player_stats(&pool, player.id, league.id) .await @@ -589,15 +651,17 @@ mod tests { } #[test] - fn check_division_iihf_points() { + fn check_division_iihf_stats() { tokio_test::block_on(async move { let pool = db_connect().await; - let score = division_iihf_stats(&pool, 1).await.unwrap(); - assert_eq!(score.get(0).unwrap().points, 10); - assert_eq!(score.get(0).unwrap().team_name, "Bullseye"); - assert_eq!(score.get(0).unwrap().reg_losses, 0); - assert_eq!(score.get(0).unwrap().ties, 2); - assert_eq!(score.get(1).unwrap().points, 4); + let score = division_iihf_stats(&pool, 1, SupportedLanguage::English).await.unwrap(); + assert_eq!(score.len(), 2, "Too many teams selected."); + assert_eq!(score.get(0).unwrap().points, 10, "Top team should have 10 points"); + assert_eq!(score.get(0).unwrap().team_name, "Bullseye", "Top team should be bullseye"); + assert_eq!(score.get(0).unwrap().reg_losses, 0, "The bullseye should have no regulation losses"); + assert_eq!(score.get(0).unwrap().ties, 2, "There should be two ties for the bullsye"); + assert_eq!(score.get(1).unwrap().team_name, "See Cats", "The second-place team should be the see cats"); + assert_eq!(score.get(1).unwrap().points, 4, "The second-place team should have four points"); }) }