1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
use anyhow::{Context, Result};
use crate::{
cli_interactor::{Interactor, InteractorPrompt, PromptInputParms},
config::{ConfigManagement, ConfigManager, MyConfig, UserRef},
};
#[derive(Default)]
pub struct UserManager {
config_manager: ConfigManager,
interactor: Interactor,
}
pub trait UserManagement {
fn add(&self, nsec: &Option<String>) -> Result<()>;
}
#[cfg(test)]
use duplicate::duplicate_item;
#[cfg_attr(test, duplicate_item(UserManager; [UserManager]; [self::tests::MockUserManager]))]
impl UserManagement for UserManager {
fn add(&self, nsec: &Option<String>) -> Result<()> {
let nsec = match nsec.clone() {
Some(nsec) => nsec,
None => self
.interactor
.input(
PromptInputParms::default().with_prompt("login with nsec (or hex private key)"),
)
.context("failed to get nsec input from interactor.input")?,
};
self.config_manager
.save(&MyConfig {
users: vec![UserRef {
nsec: nsec.to_string(),
}],
..MyConfig::default()
})
.context("failed to save application configuration with new user details in")?;
println!("logged in as {nsec}");
Ok(())
}
}
#[cfg(test)]
mod tests {
use test_utils::*;
use super::*;
use crate::{cli_interactor::MockInteractorPrompt, config::MockConfigManagement};
#[derive(Default)]
pub struct MockUserManager {
pub config_manager: MockConfigManagement,
pub interactor: MockInteractorPrompt,
}
mod add {
use super::*;
impl MockUserManager {
fn add_return_expected_responses(mut self) -> Self {
self.config_manager
.expect_load()
.returning(|| Ok(MyConfig::default()));
self.config_manager.expect_save().returning(|_| Ok(()));
self.interactor
.expect_input()
.returning(|_| Ok(TEST_KEY_1_NSEC.into()));
self
}
}
mod when_nsec_is_passed {
use super::*;
#[test]
fn user_isnt_prompted() {
let mut m = MockUserManager::default().add_return_expected_responses();
m.interactor = MockInteractorPrompt::default();
m.interactor.expect_input().never();
let _ = m.add(&Some(TEST_KEY_1_NSEC.into()));
}
}
mod when_no_nsec_is_passed {
use super::*;
#[test]
fn prompt_for_nsec() {
let mut m = MockUserManager::default().add_return_expected_responses();
m.interactor = MockInteractorPrompt::new();
m.interactor
.expect_input()
.once()
.withf(|p| p.prompt.eq("login with nsec (or hex private key)"))
.returning(|_| Ok(TEST_KEY_1_NSEC.into()));
let _ = m.add(&None);
}
#[test]
fn stored_in_config() {
let mut m = MockUserManager::default().add_return_expected_responses();
m.config_manager = MockConfigManagement::new();
m.config_manager
.expect_load()
.returning(|| Ok(MyConfig::default()));
m.config_manager
.expect_save()
.withf(|cfg| cfg.users.len().eq(&1) && cfg.users[0].nsec.eq(TEST_KEY_1_NSEC))
.returning(|_| Ok(()));
let _ = m.add(&None);
}
}
}
}
|