1
//! Integration tests for the `nomisync` automation CLI. These exercise
2
//! the clap parser and help/error pathways without needing a running
3
//! database. Actual command dispatch against the server is covered by
4
//! `cli-core`'s tests and the per-command tests inside the server crate.
5

            
6
use assert_cmd::Command;
7
use predicates::prelude::*;
8

            
9
11
fn cli() -> Command {
10
11
    Command::cargo_bin("cli").expect("cli binary should build")
11
11
}
12

            
13
#[test]
14
1
fn top_level_help_mentions_every_subcommand() {
15
1
    cli()
16
1
        .arg("--help")
17
1
        .assert()
18
1
        .success()
19
1
        .stdout(predicate::str::contains("version"))
20
1
        .stdout(predicate::str::contains("account"))
21
1
        .stdout(predicate::str::contains("transaction"))
22
1
        .stdout(predicate::str::contains("commodity"))
23
1
        .stdout(predicate::str::contains("config"))
24
1
        .stdout(predicate::str::contains("sql"))
25
1
        .stdout(predicate::str::contains("reports"))
26
1
        .stdout(predicate::str::contains("ssh-key"));
27
1
}
28

            
29
#[test]
30
1
fn ssh_key_help_lists_subcommands() {
31
1
    cli()
32
1
        .args(["ssh-key", "--help"])
33
1
        .assert()
34
1
        .success()
35
1
        .stdout(predicate::str::contains("add"))
36
1
        .stdout(predicate::str::contains("list"))
37
1
        .stdout(predicate::str::contains("remove"));
38
1
}
39

            
40
#[test]
41
1
fn ssh_key_add_requires_key_source() {
42
1
    let uuid = uuid::Uuid::new_v4();
43
1
    cli()
44
1
        .args(["--userid", &uuid.to_string(), "ssh-key", "add"])
45
1
        .assert()
46
1
        .failure()
47
1
        .stderr(predicate::str::contains("required"));
48
1
}
49

            
50
#[test]
51
1
fn ssh_key_add_rejects_both_key_sources() {
52
1
    let uuid = uuid::Uuid::new_v4();
53
1
    cli()
54
1
        .args([
55
1
            "--userid",
56
1
            &uuid.to_string(),
57
1
            "ssh-key",
58
1
            "add",
59
1
            "--key-file",
60
1
            "/tmp/foo",
61
1
            "--public-key",
62
1
            "ssh-ed25519 AAAA",
63
1
        ])
64
1
        .assert()
65
1
        .failure();
66
1
}
67

            
68
#[test]
69
1
fn ssh_key_remove_requires_fingerprint() {
70
1
    let uuid = uuid::Uuid::new_v4();
71
1
    cli()
72
1
        .args(["--userid", &uuid.to_string(), "ssh-key", "remove"])
73
1
        .assert()
74
1
        .failure()
75
1
        .stderr(predicate::str::contains("fingerprint"));
76
1
}
77

            
78
#[test]
79
1
fn reports_help_lists_subcommands() {
80
1
    cli()
81
1
        .args(["reports", "--help"])
82
1
        .assert()
83
1
        .success()
84
1
        .stdout(predicate::str::contains("balance"))
85
1
        .stdout(predicate::str::contains("activity"))
86
1
        .stdout(predicate::str::contains("breakdown"));
87
1
}
88

            
89
#[test]
90
1
fn account_help_lists_subcommands() {
91
1
    cli()
92
1
        .args(["account", "--help"])
93
1
        .assert()
94
1
        .success()
95
1
        .stdout(predicate::str::contains("list"))
96
1
        .stdout(predicate::str::contains("balance"))
97
1
        .stdout(predicate::str::contains("create"));
98
1
}
99

            
100
#[test]
101
1
fn missing_userid_exits_non_zero() {
102
1
    cli()
103
1
        .arg("version")
104
1
        .assert()
105
1
        .failure()
106
1
        .stderr(predicate::str::contains("userid"));
107
1
}
108

            
109
#[test]
110
1
fn unknown_subcommand_exits_non_zero() {
111
1
    let uuid = uuid::Uuid::new_v4();
112
1
    cli()
113
1
        .args(["--userid", &uuid.to_string(), "bogus"])
114
1
        .assert()
115
1
        .failure();
116
1
}
117

            
118
#[test]
119
1
fn reports_balance_help_documents_chart_flag() {
120
1
    cli()
121
1
        .args(["reports", "balance", "--help"])
122
1
        .assert()
123
1
        .success()
124
1
        .stdout(predicate::str::contains("chart"))
125
1
        .stdout(predicate::str::contains("from"))
126
1
        .stdout(predicate::str::contains("to"));
127
1
}
128

            
129
#[test]
130
1
fn transaction_create_rejects_malformed_value() {
131
1
    let uuid = uuid::Uuid::new_v4();
132
1
    let dummy = uuid::Uuid::new_v4();
133
1
    cli()
134
1
        .args([
135
1
            "--userid",
136
1
            &uuid.to_string(),
137
1
            "transaction",
138
1
            "create",
139
1
            "--from",
140
1
            &dummy.to_string(),
141
1
            "--to",
142
1
            &dummy.to_string(),
143
1
            "--from-currency",
144
1
            &dummy.to_string(),
145
1
            "--to-currency",
146
1
            &dummy.to_string(),
147
1
            "--value",
148
1
            "not-a-number",
149
1
        ])
150
1
        .assert()
151
1
        .failure();
152
1
}