coins_rs/
lib.rs

1pub mod currency;
2pub mod amount;
3pub mod errors;
4pub mod traits;
5pub mod ecb;
6pub mod tax;
7
8#[macro_use]
9#[cfg(test)]
10extern crate more_asserts;
11
12#[cfg(test)]
13mod tests {
14    use crate::currency::Currency;
15    use crate::amount::Amount;
16    use crate::traits::ExchangeRate;
17    use crate::errors::Error;
18    use crate::ecb::EuropeanCentralBank;
19    use crate::tax;
20
21    #[test]
22    fn test_currency_decimals() {
23        assert_eq!(0, Currency::CVE.decimals());
24        assert_eq!(2, Currency::EUR.decimals());
25        assert_eq!(3, Currency::BHD.decimals());
26    }
27
28    #[test]
29    fn test_currency_abbreviation() {
30        assert!("EUR" == Currency::EUR.abbreviation());
31        assert!("USD" == Currency::USD.abbreviation());
32    }
33    
34    #[test]
35    fn test_amount_major_minor() {
36        let amount = Amount::new(525, Currency::CVE);
37        assert_eq!(525, amount.major());
38        assert!(amount.minor().is_none());
39
40        let amount = Amount::new(525, Currency::EUR);
41        assert_eq!(5, amount.major());
42        assert!(amount.minor().is_some());
43        assert_eq!(25, amount.minor().unwrap());
44
45        let amount = Amount::new(525, Currency::BHD);
46        assert_eq!(0, amount.major());
47        assert!(amount.minor().is_some());
48        assert_eq!(525, amount.minor().unwrap());
49    }
50
51    #[test]
52    fn test_amount_add_sub() {
53        let amount1 = Amount::new(100, Currency::EUR);
54        let amount2 = Amount::new(150, Currency::EUR);
55        let amount3 = Amount::new(200, Currency::USD);
56        let expect = Amount::new(250, Currency::EUR);
57
58        let res = amount1 + amount2;
59        assert!(res.is_ok());
60        let res = res.unwrap();
61        assert_eq!(expect, res);
62        let res = res - amount2;
63        assert!(res.is_ok());
64        assert_eq!(amount1, res.unwrap());
65
66        let res = amount1 + amount3;
67        assert!(res.is_err());
68    }
69
70    #[derive(Clone, Copy)]
71    struct ExchangeRateMock;
72
73    #[derive(Clone, Copy)]
74    struct ExchangeRateErrorMock;
75
76    impl ExchangeRate for ExchangeRateMock {
77        fn exchange_rate(self, _from: Currency, _to: Currency) -> Result<f64, Error>
78        {
79            Ok(2.0f64)
80        }
81    }
82
83    impl ExchangeRate for ExchangeRateErrorMock {
84        fn exchange_rate(self, _from: Currency, _to: Currency) -> Result<f64, Error>
85        {
86            Err(Error::CouldNotGetExchangeRate)
87        }
88  }
89
90    #[test]
91    fn test_amount_exchange() {
92        let exchange_mock = ExchangeRateMock;
93        let exchange_error_mock = ExchangeRateErrorMock;
94        let amount_eur = Amount::new(100, Currency::EUR);
95        let amount_usd = amount_eur.exchange(Currency::USD, &exchange_mock);
96        assert!(amount_usd.is_ok());
97        assert_eq!(amount_usd.unwrap().amount, 200);
98        let amount_usd = amount_eur.exchange(Currency::USD, &exchange_error_mock);
99        assert!(amount_usd.is_err());
100    }
101
102    #[test]
103    fn test_ecb_exchange_rate() {
104        let ecb = EuropeanCentralBank;
105        let rate = ecb.exchange_rate(Currency::EUR, Currency::JPY);
106        assert!(rate.is_ok());
107        assert_gt!(rate.unwrap(), 1.0);
108    }
109
110    #[test]
111    fn test_tax_add() {
112        let net_amount = Amount::new(500, Currency::EUR);
113        let gross_amount = tax::add_tax(net_amount, 0.16);
114        assert_eq!(580, gross_amount.amount);
115        let tax_amount = tax::get_tax(net_amount, 0.16);
116        assert_eq!(80, tax_amount.amount);
117        let net_amount = tax::remove_tax(gross_amount, 0.16);
118        assert_eq!(500, net_amount.amount);
119    }
120}