Integration tests: homepage (WIP)

This commit is contained in:
Greg Burri 2025-04-30 01:39:11 +02:00
parent fb62288161
commit 1485110204
6 changed files with 556 additions and 41 deletions

413
Cargo.lock generated
View file

@ -109,6 +109,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "anyhow"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
[[package]]
name = "argon2"
version = "0.5.3"
@ -163,6 +169,16 @@ dependencies = [
"winnow 0.7.7",
]
[[package]]
name = "assert-json-diff"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12"
dependencies = [
"serde",
"serde_json",
]
[[package]]
name = "async-compression"
version = "0.4.23"
@ -196,6 +212,12 @@ dependencies = [
"num-traits",
]
[[package]]
name = "auto-future"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c1e7e457ea78e524f48639f551fd79703ac3f2237f5ecccdf4708f8a75ad373"
[[package]]
name = "autocfg"
version = "1.4.0"
@ -294,6 +316,36 @@ dependencies = [
"syn",
]
[[package]]
name = "axum-test"
version = "17.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eb1dfb84bd48bad8e4aa1acb82ed24c2bb5e855b659959b4e03b4dca118fcac"
dependencies = [
"anyhow",
"assert-json-diff",
"auto-future",
"axum",
"bytes",
"bytesize",
"cookie",
"http 1.3.1",
"http-body-util",
"hyper",
"hyper-util",
"mime",
"pretty_assertions",
"reserve-port",
"rust-multipart-rfc7578_2",
"serde",
"serde_json",
"serde_urlencoded",
"smallvec",
"tokio",
"tower",
"url",
]
[[package]]
name = "backtrace"
version = "0.3.74"
@ -430,6 +482,12 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "bytesize"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba"
[[package]]
name = "caseless"
version = "0.2.2"
@ -664,6 +722,29 @@ dependencies = [
"typenum",
]
[[package]]
name = "cssparser"
version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3"
dependencies = [
"cssparser-macros",
"dtoa-short",
"itoa",
"phf",
"smallvec",
]
[[package]]
name = "cssparser-macros"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "darling"
version = "0.20.11"
@ -719,12 +800,29 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "derive_more"
version = "0.99.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "deunicode"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04"
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "digest"
version = "0.10.7"
@ -754,6 +852,27 @@ version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "dtoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04"
[[package]]
name = "dtoa-short"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87"
dependencies = [
"dtoa",
]
[[package]]
name = "ego-tree"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8"
[[package]]
name = "either"
version = "1.15.0"
@ -901,6 +1020,16 @@ dependencies = [
"web-sys",
]
[[package]]
name = "futf"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
dependencies = [
"mac",
"new_debug_unreachable",
]
[[package]]
name = "futures"
version = "0.3.31"
@ -1001,6 +1130,15 @@ dependencies = [
"slab",
]
[[package]]
name = "fxhash"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
dependencies = [
"byteorder",
]
[[package]]
name = "generic-array"
version = "0.14.7"
@ -1011,6 +1149,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "getopts"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
dependencies = [
"unicode-width",
]
[[package]]
name = "getrandom"
version = "0.2.16"
@ -1306,6 +1453,18 @@ dependencies = [
"windows-link",
]
[[package]]
name = "html5ever"
version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c"
dependencies = [
"log",
"mac",
"markup5ever",
"match_token",
]
[[package]]
name = "http"
version = "0.2.12"
@ -1386,6 +1545,7 @@ dependencies = [
"pin-project-lite",
"smallvec",
"tokio",
"want",
]
[[package]]
@ -1395,13 +1555,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.3.1",
"http-body",
"hyper",
"libc",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
]
[[package]]
@ -1709,6 +1873,37 @@ version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "mac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
[[package]]
name = "markup5ever"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
dependencies = [
"log",
"phf",
"phf_codegen",
"string_cache",
"string_cache_codegen",
"tendril",
]
[[package]]
name = "match_token"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "matchers"
version = "0.1.0"
@ -1776,6 +1971,12 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nom"
version = "8.0.0"
@ -1946,6 +2147,58 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "phf"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_macros",
"phf_shared",
]
[[package]]
name = "phf_codegen"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
]
[[package]]
name = "phf_generator"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"rand 0.8.5",
]
[[package]]
name = "phf_macros"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "phf_shared"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project"
version = "1.1.10"
@ -2044,6 +2297,22 @@ dependencies = [
"zerocopy 0.8.25",
]
[[package]]
name = "precomputed-hash"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "prettyplease"
version = "0.2.32"
@ -2186,6 +2455,7 @@ dependencies = [
"async-compression",
"axum",
"axum-extra",
"axum-test",
"chrono",
"clap",
"common",
@ -2195,6 +2465,7 @@ dependencies = [
"rand 0.9.1",
"rand_core 0.9.3",
"ron",
"scraper",
"serde",
"sqlx",
"strum",
@ -2261,6 +2532,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "reserve-port"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3747658ee2585ecf5607fa9887c92eff61b362ff5253dbf797dfeb73d33d78"
dependencies = [
"thiserror 2.0.12",
]
[[package]]
name = "ring"
version = "0.17.14"
@ -2308,6 +2588,21 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rust-multipart-rfc7578_2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c839d037155ebc06a571e305af66ff9fd9063a6e662447051737e1ac75beea41"
dependencies = [
"bytes",
"futures-core",
"futures-util",
"http 1.3.1",
"mime",
"rand 0.9.1",
"thiserror 2.0.12",
]
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@ -2401,6 +2696,40 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "scraper"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "527e65d9d888567588db4c12da1087598d0f6f8b346cc2c5abc91f05fc2dffe2"
dependencies = [
"cssparser",
"ego-tree",
"getopts",
"html5ever",
"precomputed-hash",
"selectors",
"tendril",
]
[[package]]
name = "selectors"
version = "0.26.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8"
dependencies = [
"bitflags 2.9.0",
"cssparser",
"derive_more",
"fxhash",
"log",
"new_debug_unreachable",
"phf",
"phf_codegen",
"precomputed-hash",
"servo_arc",
"smallvec",
]
[[package]]
name = "serde"
version = "1.0.219"
@ -2479,6 +2808,15 @@ dependencies = [
"serde",
]
[[package]]
name = "servo_arc"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a"
dependencies = [
"stable_deref_trait",
]
[[package]]
name = "sha1"
version = "0.10.6"
@ -2541,6 +2879,12 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "siphasher"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
[[package]]
name = "slab"
version = "0.4.9"
@ -2810,6 +3154,31 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "string_cache"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
dependencies = [
"new_debug_unreachable",
"parking_lot",
"phf_shared",
"precomputed-hash",
"serde",
]
[[package]]
name = "string_cache_codegen"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2",
"quote",
]
[[package]]
name = "stringprep"
version = "0.1.5"
@ -2916,6 +3285,17 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "tendril"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
dependencies = [
"futf",
"mac",
"utf-8",
]
[[package]]
name = "terminal_size"
version = "0.4.2"
@ -3239,6 +3619,12 @@ dependencies = [
"tracing-log",
]
[[package]]
name = "try-lock"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
name = "typed-arena"
version = "2.0.2"
@ -3284,6 +3670,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode_categories"
version = "0.1.1"
@ -3313,6 +3705,12 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a1f0175e03a0973cf4afd476bef05c26e228520400eb1fd473ad417b1c00ffb"
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf16_iter"
version = "1.0.5"
@ -3359,6 +3757,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -3785,6 +4192,12 @@ dependencies = [
"linked-hash-map",
]
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yoke"
version = "0.7.5"

View file

@ -49,3 +49,7 @@ lettre = { version = "0.11", default-features = false, features = [
] }
thiserror = "2"
[dev-dependencies]
axum-test = "17"
scraper = "0.23"

View file

@ -59,7 +59,6 @@ impl Connection {
Self::new_from_file(path).await
}
#[cfg(test)]
pub async fn new_in_memory() -> Result<Connection> {
Self::create_connection(SqlitePoolOptions::new().connect("sqlite::memory:").await?).await
}

View file

@ -29,13 +29,16 @@ const TRACING_LEVEL: tracing::Level = tracing::Level::INFO;
const TRACING_DISPLAY_THREAD: bool = false;
#[derive(Clone)]
pub struct Log {
_guard: Arc<WorkerGuard>,
directory: PathBuf,
pub enum Log {
FileAndStdout {
_guard: Arc<WorkerGuard>,
directory: PathBuf,
},
StdoutOnly,
}
impl Log {
pub fn new<P>(directory: P) -> Self
pub fn new_to_directory<P>(directory: P) -> Self
where
P: AsRef<Path>,
{
@ -68,51 +71,69 @@ impl Log {
.with(layer_stdout)
.init();
Log {
Log::FileAndStdout {
_guard: Arc::new(guard),
directory: directory.as_ref().to_path_buf(),
}
}
pub fn file_names(&self) -> std::io::Result<Vec<String>> {
fn dir_entry_to_string(entry: Result<DirEntry, io::Error>) -> String {
entry.map_or_else(
|err| format!("Unable to read entry: {}", err),
|entry| {
entry
.path()
.file_name()
.map_or("Unable to read filename".into(), |filename| {
filename
.to_str()
.map_or("Unable to read filename".into(), |filename| {
filename.to_string()
})
})
},
)
}
pub fn new_stdout_only() -> Self {
let layer_stdout = tracing_subscriber::fmt::layer()
.with_writer(std::io::stdout.with_max_level(TRACING_LEVEL))
.with_thread_ids(TRACING_DISPLAY_THREAD)
.with_thread_names(TRACING_DISPLAY_THREAD);
Ok(self
.directory
.read_dir()?
.map(dir_entry_to_string)
.sorted()
.rev()
.collect())
tracing_subscriber::Registry::default()
.with(layer_stdout)
.init();
Log::StdoutOnly
}
pub fn file_names(&self) -> std::io::Result<Vec<String>> {
match self {
Log::FileAndStdout { _guard, directory } => {
fn dir_entry_to_string(entry: Result<DirEntry, io::Error>) -> String {
entry.map_or_else(
|err| format!("Unable to read entry: {}", err),
|entry| {
entry.path().file_name().map_or(
"Unable to read filename".into(),
|filename| {
filename
.to_str()
.map_or("Unable to read filename".into(), |filename| {
filename.to_string()
})
},
)
},
)
}
Ok(directory
.read_dir()?
.map(dir_entry_to_string)
.sorted()
.rev()
.collect())
}
Log::StdoutOnly => Ok(vec![]),
}
}
/// Reads the content of a log file and return it as a vector of lines.
pub fn read_content(&self, filename: &str) -> std::io::Result<Vec<String>> {
let filepath = self.directory.join(filename);
if filepath.is_file() {
let file = File::open(filepath)?;
Ok(BufReader::new(file)
.lines()
.map(|l| l.unwrap_or_default())
.collect())
} else {
Ok(vec![])
match self {
Log::FileAndStdout { _guard, directory } => {
let filepath = directory.join(filename);
let file = File::open(filepath)?;
Ok(BufReader::new(file)
.lines()
.map(|l| l.unwrap_or_default())
.collect())
}
Log::StdoutOnly => Ok(vec![]),
}
}

View file

@ -15,7 +15,7 @@ use recipes::{
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = config::load();
let log = Log::new(&config.logs_directory);
let log = Log::new_to_directory(&config.logs_directory);
event!(Level::INFO, "Configuration: {:?}", config);

78
backend/tests/http.rs Normal file
View file

@ -0,0 +1,78 @@
use std::error::Error;
use axum_test::TestServer;
use scraper::Html;
use recipes::{app, config, data::db, log};
#[tokio::test]
async fn homepage() -> Result<(), Box<dyn Error>> {
// Arrange.
let state = common_state().await?;
let user_id = create_user(&state.db_connection, "president@spaceball.planet", "12345").await?;
let _recipe_id = create_recipe(&state.db_connection, user_id, "spaghetti").await?;
let server = TestServer::new(app::make_service(state))?;
// Act.
let response = server.get("/").await;
// Assert.
response.assert_status_ok();
// TODO: check if 'spaghetti' is in the list.
let document = Html::parse_document(&response.text());
assert_eq!(document.errors.len(), 0);
// println!("{:?}", document.errors);
// println!("{:?}", response);
Ok(())
}
async fn create_user(
db_connection: &db::Connection,
email: &str,
password: &str,
) -> Result<i64, Box<dyn Error>> {
if let db::user::SignUpResult::UserCreatedWaitingForValidation(token) = db_connection
.sign_up(email, password, chrono::Weekday::Mon)
.await?
{
if let db::user::ValidationResult::Ok(_, user_id) = db_connection
.validation(
&token,
chrono::Duration::hours(1),
"127.0.0.1",
"Mozilla/5.0",
)
.await?
{
Ok(user_id)
} else {
Err(Box::<dyn Error>::from("Unable to validate user"))
}
} else {
Err(Box::<dyn Error>::from("Unable to sign up"))
}
}
async fn create_recipe(
db_connection: &db::Connection,
user_id: i64,
title: &str,
) -> Result<i64, Box<dyn Error>> {
let recipe_id = db_connection.create_recipe(user_id).await?;
db_connection.set_recipe_title(recipe_id, title).await?;
db_connection.set_recipe_is_public(recipe_id, true).await?;
Ok(recipe_id)
}
async fn common_state() -> Result<app::AppState, Box<dyn Error>> {
let db_connection = db::Connection::new_in_memory().await?;
let config = config::Config::default();
let log = log::Log::new_stdout_only();
Ok(app::AppState {
config,
db_connection,
log,
})
}