cli: Add integration tests for CLI interface

Closes #10
grcov
Manos Pitsidianakis 2023-04-18 14:05:47 +03:00
parent faa90fe52a
commit 7880e668b6
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
4 changed files with 338 additions and 1 deletions

150
Cargo.lock generated
View File

@ -13,6 +13,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -22,6 +31,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anstyle"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
[[package]]
name = "anyhow"
version = "1.0.70"
@ -40,6 +55,21 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "assert_cmd"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86d6b683edf8d1119fe420a94f8a7e389239666aa72e65495d91c00462510151"
dependencies = [
"anstyle",
"bstr",
"doc-comment",
"predicates",
"predicates-core",
"predicates-tree",
"wait-timeout",
]
[[package]]
name = "async-channel"
version = "1.8.0"
@ -422,6 +452,18 @@ dependencies = [
"log",
]
[[package]]
name = "bstr"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09"
dependencies = [
"memchr",
"once_cell",
"regex-automata",
"serde",
]
[[package]]
name = "bufstream"
version = "0.1.4"
@ -689,6 +731,12 @@ version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb"
[[package]]
name = "difflib"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
[[package]]
name = "digest"
version = "0.9.0"
@ -729,6 +777,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]]
name = "dyn-clone"
version = "1.0.11"
@ -893,6 +947,15 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "float-cmp"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
dependencies = [
"num-traits",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1364,6 +1427,15 @@ version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.6"
@ -1515,11 +1587,14 @@ dependencies = [
name = "mailpot-cli"
version = "0.0.0+2023-04-07"
dependencies = [
"assert_cmd",
"clap",
"clap_mangen",
"log",
"mailpot",
"predicates",
"stderrlog",
"tempfile",
]
[[package]]
@ -1780,6 +1855,12 @@ dependencies = [
"minimal-lexical",
]
[[package]]
name = "normalize-line-endings"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
[[package]]
name = "notify"
version = "4.0.17"
@ -1978,6 +2059,37 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "predicates"
version = "3.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09963355b9f467184c04017ced4a2ba2d75cbcb4e7462690d388233253d4b1a9"
dependencies = [
"anstyle",
"difflib",
"float-cmp",
"itertools",
"normalize-line-endings",
"predicates-core",
"regex",
]
[[package]]
name = "predicates-core"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174"
[[package]]
name = "predicates-tree"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf"
dependencies = [
"predicates-core",
"termtree",
]
[[package]]
name = "proc-macro2"
version = "1.0.56"
@ -2055,6 +2167,29 @@ dependencies = [
"thiserror",
]
[[package]]
name = "regex"
version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "reqwest"
version = "0.11.16"
@ -2523,6 +2658,12 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "termtree"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
[[package]]
name = "ternop"
version = "1.0.1"
@ -2905,6 +3046,15 @@ version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wait-timeout"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
dependencies = [
"libc",
]
[[package]]
name = "waker-fn"
version = "1.1.0"

View File

@ -21,6 +21,11 @@ log = "0.4"
mailpot = { version = "^0.0", path = "../core" }
stderrlog = "^0.5"
[dev-dependencies]
assert_cmd = "2"
predicates = "3"
tempfile = "3.3"
[build-dependencies]
clap = { version = "^4.2", default-features = false, features = ["derive", "cargo", "unicode", "wrap_help", "help", "usage", "error-context", "suggestions"] }
clap_mangen = "0.2.10"

View File

@ -0,0 +1,182 @@
/*
* meli - email module
*
* Copyright 2019 Manos Pitsidianakis
*
* This file is part of meli.
*
* meli is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* meli is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with meli. If not, see <http://www.gnu.org/licenses/>.
*/
#![deny(dead_code)]
use std::path::Path;
use assert_cmd::assert::OutputAssertExt;
use mailpot::{models::*, Configuration, Connection, SendMail};
use predicates::prelude::*;
use tempfile::TempDir;
#[test]
fn test_cli_basic_interfaces() {
use assert_cmd::Command;
fn no_args() {
let mut cmd = Command::cargo_bin("mpot").unwrap();
// 2 -> incorrect usage
cmd.assert().code(2);
}
fn version() {
// --version is successful
for arg in ["--version", "-V"] {
let mut cmd = Command::cargo_bin("mpot").unwrap();
let output = cmd.arg(dbg!(arg)).output().unwrap().assert();
output.code(0).stdout(predicates::str::starts_with("mpot "));
}
}
fn help() {
// --help is successful
for (arg, starts_with) in [
("--help", "GNU Affero version 3 or later"),
("-h", "mailing list manager"),
] {
let mut cmd = Command::cargo_bin("mpot").unwrap();
let output = cmd.arg(dbg!(arg)).output().unwrap().assert();
output
.code(0)
.stdout(predicates::str::starts_with(starts_with))
.stdout(predicates::str::contains("Usage:"));
}
}
fn sample_config() {
let mut cmd = Command::cargo_bin("mpot").unwrap();
// sample-config does not require a configuration file as an argument (but other
// commands do)
let output = cmd.arg("sample-config").output().unwrap().assert();
output.code(0).stdout(predicates::str::is_empty().not());
}
fn config_required() {
let mut cmd = Command::cargo_bin("mpot").unwrap();
let output = cmd.arg("list-lists").output().unwrap().assert();
output.code(2).stdout(predicates::str::is_empty()).stderr(
predicate::eq(
r#"error: --config is required for mailing list operations
Usage: mpot [OPTIONS] <COMMAND>
For more information, try '--help'."#,
)
.trim()
.normalize(),
);
}
no_args();
version();
help();
sample_config();
config_required();
let tmp_dir = TempDir::new().unwrap();
let conf_path = tmp_dir.path().join("conf.toml");
let db_path = tmp_dir.path().join("mpot.db");
let config = Configuration {
send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
db_path,
data_path: tmp_dir.path().to_path_buf(),
};
let config_str = config.to_toml();
std::fs::write(&conf_path, &config_str.as_bytes()).unwrap();
fn list_lists(conf: &Path, eq: &str) {
let mut cmd = Command::cargo_bin("mpot").unwrap();
let output = cmd
.arg("-c")
.arg(conf)
.arg("list-lists")
.output()
.unwrap()
.assert();
output
.code(0)
.stderr(predicates::str::is_empty())
.stdout(predicate::eq(eq).trim().normalize());
}
list_lists(&conf_path, "No lists found.");
{
let db = Connection::open_or_create_db(config.clone())
.unwrap()
.trusted();
let foo_chat = db
.create_list(MailingList {
pk: 0,
name: "foobar chat".into(),
id: "foo-chat".into(),
address: "foo-chat@example.com".into(),
description: None,
archive_url: None,
})
.unwrap();
assert_eq!(foo_chat.pk(), 1);
}
list_lists(
&conf_path,
"- foo-chat DbVal(MailingList { pk: 1, name: \"foobar chat\", id: \"foo-chat\", address: \
\"foo-chat@example.com\", description: None, archive_url: None }, 1)\n\tList owners: \
None\n\tList policy: None",
);
fn create_list(conf: &Path) {
let mut cmd = Command::cargo_bin("mpot").unwrap();
let output = cmd
.arg("-c")
.arg(conf)
.arg("create-list")
.arg("--name")
.arg("twobar")
.arg("--id")
.arg("twobar-chat")
.arg("--address")
.arg("twobar-chat@example.com")
.output()
.unwrap()
.assert();
output.code(0).stderr(predicates::str::is_empty()).stdout(
predicate::eq("Created new list \"twobar-chat\" with primary key 2")
.trim()
.normalize(),
);
}
create_list(&conf_path);
list_lists(
&conf_path,
"- foo-chat DbVal(MailingList { pk: 1, name: \"foobar chat\", id: \"foo-chat\", address: \
\"foo-chat@example.com\", description: None, archive_url: None }, 1)\n\tList owners: \
None\n\tList policy: None\n\n- twobar-chat DbVal(MailingList { pk: 2, name: \"twobar\", \
id: \"twobar-chat\", address: \"twobar-chat@example.com\", description: None, \
archive_url: None }, 2)\n\tList owners: None\n\tList policy: None",
);
}

View File

@ -27,4 +27,4 @@ xdg = "2.4.1"
mailin-embedded = { version = "0.7", features = ["rtls"] }
reqwest = { version = "0.11", default-features = false, features = ["json", "blocking"] }
stderrlog = "^0.5"
tempfile = "3.3.0"
tempfile = "3.3"