Skip to content

Commit a11ad77

Browse files
authored
Use rstest for parameterized tests, up version, baseline tests (#463)
1 parent bea60fe commit a11ad77

File tree

14 files changed

+207
-30
lines changed

14 files changed

+207
-30
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# 0.3.4
2+
3+
* Add in-depth tests for bill validation
4+
15
# 0.3.3
26

37
* Use Nip-04 as a default for Nostr communication

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ nostr-sdk = { version = "0.40", features = ["nip04", "nip59"] }
3838
getrandom = { version = "0.3.1", features = ["wasm_js"] }
3939
reqwest = { version = "0.12", default-features = false, features = ["json"] }
4040
async-broadcast = "0.7.2"
41+
rstest = "0.25.0"

crates/bcr-ebill-api/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bcr-ebill-api"
3-
version = "0.3.3"
3+
version = "0.3.4"
44
edition = "2024"
55

66
[lib]

crates/bcr-ebill-core/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bcr-ebill-core"
3-
version = "0.3.3"
3+
version = "0.3.4"
44
edition = "2024"
55

66
[lib]
@@ -21,3 +21,6 @@ bip39.workspace = true
2121
ecies.workspace = true
2222
nostr-sdk.workspace = true
2323
rust_decimal = { version = "1.36.0", default-features = false }
24+
25+
[dev-dependencies]
26+
rstest.workspace = true

crates/bcr-ebill-core/src/blockchain/bill/block.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,10 +1402,12 @@ mod tests {
14021402
use crate::{
14031403
blockchain::bill::tests::get_baseline_identity,
14041404
tests::tests::{
1405-
TEST_BILL_ID, TEST_PRIVATE_KEY_SECP, empty_bitcredit_bill, empty_identity_public_data,
1406-
get_bill_keys, identity_public_data_only_node_id,
1405+
TEST_BILL_ID, TEST_PRIVATE_KEY_SECP, TEST_PUB_KEY_SECP, empty_bitcredit_bill,
1406+
empty_identity_public_data, get_bill_keys, identity_public_data_only_node_id,
1407+
valid_address,
14071408
},
14081409
};
1410+
use rstest::rstest;
14091411

14101412
fn get_first_block() -> BillBlock {
14111413
let mut bill = empty_bitcredit_bill();
@@ -2691,4 +2693,47 @@ mod tests {
26912693
let result = block.verify_and_get_signer(&bill_keys_obj);
26922694
assert!(result.is_err());
26932695
}
2696+
2697+
// Validation
2698+
2699+
fn valid_bill_identity_block_data() -> BillIdentityBlockData {
2700+
BillIdentityBlockData {
2701+
t: ContactType::Person,
2702+
node_id: TEST_PUB_KEY_SECP.into(),
2703+
name: "Johanna Smith".into(),
2704+
postal_address: valid_address(),
2705+
}
2706+
}
2707+
2708+
#[test]
2709+
fn test_valid_bill_identity_block_data() {
2710+
assert_eq!(valid_bill_identity_block_data().validate(), Ok(()));
2711+
}
2712+
2713+
#[rstest]
2714+
#[case::invalid_node_id(
2715+
BillIdentityBlockData { node_id: "invalidkey".into(), ..valid_bill_identity_block_data() },
2716+
ValidationError::InvalidSecp256k1Key("invalidkey".into())
2717+
)]
2718+
#[case::empty_name(
2719+
BillIdentityBlockData { name: "".into(), ..valid_bill_identity_block_data() },
2720+
ValidationError::FieldEmpty(Field::Name)
2721+
)]
2722+
#[case::blank_name(
2723+
BillIdentityBlockData { name: " ".into(), ..valid_bill_identity_block_data() },
2724+
ValidationError::FieldEmpty(Field::Name)
2725+
)]
2726+
#[case::invalid_address(
2727+
BillIdentityBlockData {
2728+
postal_address: PostalAddress { country: "".into(), ..valid_address() },
2729+
..valid_bill_identity_block_data()
2730+
},
2731+
ValidationError::FieldEmpty(Field::Country)
2732+
)]
2733+
fn test_invalid_identity_data(
2734+
#[case] identity: BillIdentityBlockData,
2735+
#[case] expected_error: ValidationError,
2736+
) {
2737+
assert_eq!(identity.validate(), Err(expected_error));
2738+
}
26942739
}

crates/bcr-ebill-core/src/blockchain/company/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ impl CompanyBlockchain {
474474
mod tests {
475475
use super::*;
476476
use crate::tests::tests::{
477-
TEST_PRIVATE_KEY_SECP, TEST_PUB_KEY_SECP, empty_address, empty_optional_address,
477+
TEST_PRIVATE_KEY_SECP, TEST_PUB_KEY_SECP, valid_address, valid_optional_address,
478478
};
479479

480480
fn get_baseline_company_data() -> (String, (Company, CompanyKeys)) {
@@ -486,7 +486,7 @@ mod tests {
486486
name: "some_name".to_string(),
487487
country_of_registration: Some("AT".to_string()),
488488
city_of_registration: Some("Vienna".to_string()),
489-
postal_address: empty_address(),
489+
postal_address: valid_address(),
490490
email: "[email protected]".to_string(),
491491
registration_number: Some("some_number".to_string()),
492492
registration_date: Some("2012-01-01".to_string()),
@@ -536,7 +536,7 @@ mod tests {
536536
&CompanyUpdateBlockData {
537537
name: Some("new_name".to_string()),
538538
email: None,
539-
postal_address: empty_optional_address(),
539+
postal_address: valid_optional_address(),
540540
country_of_registration: None,
541541
city_of_registration: None,
542542
registration_number: None,

crates/bcr-ebill-core/src/blockchain/identity/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ impl IdentityBlockchain {
391391
#[cfg(test)]
392392
mod tests {
393393
use super::*;
394-
use crate::tests::tests::{empty_identity, empty_optional_address};
394+
use crate::tests::tests::{empty_identity, valid_optional_address};
395395

396396
#[test]
397397
fn create_and_check_validity() {
@@ -417,7 +417,7 @@ mod tests {
417417
&IdentityUpdateBlockData {
418418
name: Some("newname".to_string()),
419419
email: None,
420-
postal_address: empty_optional_address(),
420+
postal_address: valid_optional_address(),
421421
date_of_birth: None,
422422
country_of_birth: None,
423423
city_of_birth: None,

crates/bcr-ebill-core/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub struct UploadFileResult {
150150
pub file_upload_id: String,
151151
}
152152

153-
#[derive(Debug)]
153+
#[derive(Debug, Clone, Eq, PartialEq)]
154154
pub enum Field {
155155
Country,
156156
City,
@@ -166,7 +166,7 @@ pub enum Field {
166166
}
167167

168168
/// Generic validation error type
169-
#[derive(Debug, Error)]
169+
#[derive(Debug, Error, Eq, PartialEq)]
170170
pub enum ValidationError {
171171
/// error returned if a field that is not allowed to be empty is empty
172172
#[error("Field {0:?} can't be empty")]

crates/bcr-ebill-core/src/tests/mod.rs

Lines changed: 135 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,158 @@
11
#[cfg(test)]
22
#[allow(clippy::module_inception)]
33
pub mod tests {
4+
use crate::Validate;
45
use crate::{
5-
OptionalPostalAddress, PostalAddress,
6+
Field, OptionalPostalAddress, PostalAddress, ValidationError,
67
bill::{BillKeys, BitcreditBill},
78
contact::{ContactType, IdentityPublicData},
89
identity::Identity,
910
};
11+
use rstest::rstest;
1012

11-
pub fn empty_address() -> PostalAddress {
13+
pub fn valid_address() -> PostalAddress {
1214
PostalAddress {
13-
country: "AT".to_string(),
14-
city: "Vienna".to_string(),
15-
zip: None,
16-
address: "Some address".to_string(),
15+
country: "AT".into(),
16+
city: "Vienna".into(),
17+
zip: Some("1010".into()),
18+
address: "Kärntner Straße 1".into(),
1719
}
1820
}
1921

20-
pub fn empty_optional_address() -> OptionalPostalAddress {
22+
#[rstest]
23+
#[case::empty_country(
24+
PostalAddress { country: "".into(), ..valid_address() },
25+
ValidationError::FieldEmpty(Field::Country)
26+
)]
27+
#[case::blank_country(
28+
PostalAddress { country: " ".into(), ..valid_address() },
29+
ValidationError::FieldEmpty(Field::Country)
30+
)]
31+
#[case::empty_city(
32+
PostalAddress { city: "".into(), ..valid_address() },
33+
ValidationError::FieldEmpty(Field::City)
34+
)]
35+
#[case::blank_city(
36+
PostalAddress { city: " ".into(), ..valid_address() },
37+
ValidationError::FieldEmpty(Field::City)
38+
)]
39+
#[case::empty_zip(
40+
PostalAddress { zip: Some("".into()), ..valid_address() },
41+
ValidationError::FieldEmpty(Field::Zip)
42+
)]
43+
#[case::blank_zip(
44+
PostalAddress { zip: Some(" ".into()), ..valid_address() },
45+
ValidationError::FieldEmpty(Field::Zip)
46+
)]
47+
#[case::empty_address(
48+
PostalAddress { address: "".into(), ..valid_address() },
49+
ValidationError::FieldEmpty(Field::Address)
50+
)]
51+
#[case::blank_address(
52+
PostalAddress { address: " ".into(), ..valid_address() },
53+
ValidationError::FieldEmpty(Field::Address)
54+
)]
55+
fn test_invalid_address_cases(
56+
#[case] address: PostalAddress,
57+
#[case] expected_error: ValidationError,
58+
) {
59+
assert_eq!(address.validate(), Err(expected_error));
60+
}
61+
62+
#[rstest]
63+
#[case::baseline(valid_address())]
64+
#[case::spaced_country(PostalAddress {
65+
zip: Some("1020".into()),
66+
country: " AT ".into(),
67+
..valid_address()
68+
})]
69+
#[case::no_zip(
70+
PostalAddress { zip: None, ..valid_address() },
71+
)]
72+
#[case::spaced_zip(PostalAddress {
73+
zip: Some(" Some Street 1 ".into()),
74+
..valid_address()
75+
})]
76+
#[case::spaced_zip_address(PostalAddress {
77+
zip: Some(" 10101 ".into()),
78+
address: " 56 Rue de Paris ".into(),
79+
..valid_address()
80+
})]
81+
fn test_valid_addresses(#[case] address: PostalAddress) {
82+
assert_eq!(address.validate(), Ok(()));
83+
}
84+
85+
pub fn valid_optional_address() -> OptionalPostalAddress {
2186
OptionalPostalAddress {
22-
country: None,
23-
city: None,
24-
zip: None,
25-
address: None,
87+
country: Some("AT".into()),
88+
city: Some("Vienna".into()),
89+
zip: Some("1010".into()),
90+
address: Some("Kärntner Straße 1".into()),
2691
}
2792
}
2893

94+
#[test]
95+
fn test_valid_optional_address() {
96+
let address = valid_optional_address();
97+
assert_eq!(address.validate(), Ok(()));
98+
assert_eq!(
99+
OptionalPostalAddress {
100+
country: None,
101+
city: None,
102+
zip: None,
103+
address: None
104+
}
105+
.validate(),
106+
Ok(())
107+
);
108+
}
109+
110+
#[rstest]
111+
#[case::empty_country(
112+
OptionalPostalAddress { country: Some("".into()), ..valid_optional_address() },
113+
ValidationError::FieldEmpty(Field::Country)
114+
)]
115+
#[case::blank_country(
116+
OptionalPostalAddress { country: Some(" ".into()), ..valid_optional_address() },
117+
ValidationError::FieldEmpty(Field::Country)
118+
)]
119+
#[case::empty_city(
120+
OptionalPostalAddress { city: Some("".into()), ..valid_optional_address() },
121+
ValidationError::FieldEmpty(Field::City)
122+
)]
123+
#[case::blank_city(
124+
OptionalPostalAddress { city: Some("\n\t".into()), ..valid_optional_address() },
125+
ValidationError::FieldEmpty(Field::City)
126+
)]
127+
#[case::empty_zip(
128+
OptionalPostalAddress { zip: Some("".into()), ..valid_optional_address() },
129+
ValidationError::FieldEmpty(Field::Zip)
130+
)]
131+
#[case::blank_zip(
132+
OptionalPostalAddress { zip: Some(" ".into()), ..valid_optional_address() },
133+
ValidationError::FieldEmpty(Field::Zip)
134+
)]
135+
#[case::empty_address(
136+
OptionalPostalAddress { address: Some("".into()), ..valid_optional_address() },
137+
ValidationError::FieldEmpty(Field::Address)
138+
)]
139+
#[case::blank_address(
140+
OptionalPostalAddress { address: Some(" ".into()), ..valid_optional_address() },
141+
ValidationError::FieldEmpty(Field::Address)
142+
)]
143+
fn test_optional_address(
144+
#[case] address: OptionalPostalAddress,
145+
#[case] expected_error: ValidationError,
146+
) {
147+
assert_eq!(address.validate(), Err(expected_error));
148+
}
149+
29150
pub fn empty_identity() -> Identity {
30151
Identity {
31152
node_id: "".to_string(),
32153
name: "some name".to_string(),
33154
email: "[email protected]".to_string(),
34-
postal_address: empty_optional_address(),
155+
postal_address: valid_optional_address(),
35156
date_of_birth: None,
36157
country_of_birth: None,
37158
city_of_birth: None,
@@ -47,7 +168,7 @@ pub mod tests {
47168
t: ContactType::Person,
48169
node_id: "".to_string(),
49170
name: "some name".to_string(),
50-
postal_address: empty_address(),
171+
postal_address: valid_address(),
51172
email: None,
52173
nostr_relay: None,
53174
}
@@ -58,7 +179,7 @@ pub mod tests {
58179
t: ContactType::Person,
59180
node_id,
60181
name: "some name".to_string(),
61-
postal_address: empty_address(),
182+
postal_address: valid_address(),
62183
email: None,
63184
nostr_relay: None,
64185
}

crates/bcr-ebill-persistence/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bcr-ebill-persistence"
3-
version = "0.3.3"
3+
version = "0.3.4"
44
edition = "2024"
55

66
[lib]

0 commit comments

Comments
 (0)