ofx 0.2.9 → 0.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,34 +11,121 @@ describe OFX::Account do
11
11
  it "should return currency" do
12
12
  @account.currency.should == "BRL"
13
13
  end
14
-
14
+
15
15
  it "should return bank id" do
16
16
  @account.bank_id.should == "0356"
17
17
  end
18
-
18
+
19
19
  it "should return id" do
20
20
  @account.id.should == "03227113109"
21
21
  end
22
-
22
+
23
23
  it "should return type" do
24
24
  @account.type.should == :checking
25
25
  end
26
-
26
+
27
27
  it "should return transactions" do
28
28
  @account.transactions.should be_a_kind_of(Array)
29
29
  @account.transactions.size.should == 36
30
30
  end
31
-
31
+
32
32
  it "should return balance" do
33
- @account.balance.amount.should == 598.44
33
+ @account.balance.amount.should == BigDecimal('598.44')
34
34
  end
35
-
35
+
36
36
  it "should return balance in pennies" do
37
37
  @account.balance.amount_in_pennies.should == 59844
38
38
  end
39
-
39
+
40
40
  it "should return balance date" do
41
- @account.balance.posted_at.should == Time.parse("2009-11-01")
41
+ @account.balance.posted_at.should == Time.gm(2009,11,1)
42
+ end
43
+
44
+ context "available_balance" do
45
+ it "should return available balance" do
46
+ @account.available_balance.amount.should == BigDecimal('1555.99')
47
+ end
48
+
49
+ it "should return available balance in pennies" do
50
+ @account.available_balance.amount_in_pennies.should == 155599
51
+ end
52
+
53
+ it "should return available balance date" do
54
+ @account.available_balance.posted_at.should == Time.gm(2009,11,1)
55
+ end
56
+
57
+ it "should return nil if AVAILBAL not found" do
58
+ @ofx = OFX::Parser::Base.new("spec/fixtures/utf8.ofx")
59
+ @parser = @ofx.parser
60
+ @account = @parser.account
61
+ @account.available_balance.should be_nil
62
+ end
63
+ end
64
+
65
+ context "Credit Card" do
66
+ before do
67
+ @ofx = OFX::Parser::Base.new("spec/fixtures/creditcard.ofx")
68
+ @parser = @ofx.parser
69
+ @account = @parser.account
70
+ end
71
+
72
+ it "should return id" do
73
+ @account.id.should == "XXXXXXXXXXXX1111"
74
+ end
75
+
76
+ it "should return currency" do
77
+ @account.currency.should == "USD"
78
+ end
79
+ end
80
+ context "With Issue" do # Bradesco do not provide a valid date in balance
81
+ before do
82
+ @ofx = OFX::Parser::Base.new("spec/fixtures/dtsof_balance_issue.ofx")
83
+ @parser = @ofx.parser
84
+ @account = @parser.account
85
+ end
86
+
87
+ it "should return nil for date balance" do
88
+ @account.balance.posted_at.should be_nil
89
+ end
90
+ end
91
+
92
+ context "Invalid Dates" do
93
+ before do
94
+ @ofx = OFX::Parser::Base.new("spec/fixtures/bradesco.ofx")
95
+ @parser = @ofx.parser
96
+ end
97
+ it "should not raise error when balance has date zero" do
98
+ expect { @parser.account.balance }.to_not raise_error
99
+ end
100
+ it "should return NIL in balance.posted_at when balance date is zero" do
101
+ @parser.account.balance.posted_at.should be_nil
102
+ end
103
+ end
104
+
105
+ context "decimal values using a comma" do
106
+ before do
107
+ @ofx = OFX::Parser::Base.new("spec/fixtures/santander.ofx")
108
+ @parser = @ofx.parser
109
+ @account = @parser.account
110
+ end
111
+
112
+ it "should return balance" do
113
+ @account.balance.amount.should == BigDecimal('348.29')
114
+ end
115
+
116
+ it "should return balance in pennies" do
117
+ @account.balance.amount_in_pennies.should == 34829
118
+ end
119
+
120
+ context "available_balance" do
121
+ it "should return available balance" do
122
+ @account.available_balance.amount.should == BigDecimal('2415.87')
123
+ end
124
+
125
+ it "should return available balance in pennies" do
126
+ @account.available_balance.amount_in_pennies.should == 241587
127
+ end
128
+ end
42
129
  end
43
130
  end
44
131
  end
@@ -5,20 +5,63 @@ describe OFX::Parser::OFX102 do
5
5
  @ofx = OFX::Parser::Base.new("spec/fixtures/sample.ofx")
6
6
  @parser = @ofx.parser
7
7
  end
8
-
8
+
9
9
  it "should have a version" do
10
10
  OFX::Parser::OFX102::VERSION.should == "1.0.2"
11
11
  end
12
-
12
+
13
13
  it "should set headers" do
14
14
  @parser.headers.should == @ofx.headers
15
15
  end
16
-
16
+
17
+ it "should trim trailing whitespace from headers" do
18
+ headers = OFX::Parser::OFX102.parse_headers("VERSION:102 ")
19
+ headers["VERSION"].should == "102"
20
+ end
21
+
17
22
  it "should set body" do
18
23
  @parser.body.should == @ofx.body
19
24
  end
20
-
25
+
21
26
  it "should set account" do
22
27
  @parser.account.should be_a_kind_of(OFX::Account)
23
28
  end
24
- end
29
+
30
+ it "should set account" do
31
+ @parser.sign_on.should be_a_kind_of(OFX::SignOn)
32
+ end
33
+
34
+ it "should set statements" do
35
+ @parser.statements.size.should == 1
36
+ @parser.statements.first.should be_a_kind_of(OFX::Statement)
37
+ end
38
+
39
+ it "should know about all transaction types" do
40
+ valid_types = [
41
+ 'CREDIT', 'DEBIT', 'INT', 'DIV', 'FEE', 'SRVCHG', 'DEP', 'ATM', 'POS', 'XFER',
42
+ 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER'
43
+ ]
44
+ valid_types.sort.should == OFX::Parser::OFX102::TRANSACTION_TYPES.keys.sort
45
+
46
+ valid_types.each do |transaction_type|
47
+ transaction_type.downcase.to_sym.should equal OFX::Parser::OFX102::TRANSACTION_TYPES[transaction_type]
48
+ end
49
+ end
50
+
51
+ describe "#build_date" do
52
+ context "without a Time Zone" do
53
+ it "should default to GMT" do
54
+ @parser.send(:build_date, "20170904").should == Time.gm(2017, 9, 4)
55
+ @parser.send(:build_date, "20170904082855").should == Time.gm(2017, 9, 4, 8, 28, 55)
56
+ end
57
+ end
58
+
59
+ context "with a Time Zone" do
60
+ it "should returns the correct date" do
61
+ @parser.send(:build_date, "20150507164333[-0300:BRT]").should == Time.new(2015, 5, 7, 16, 43, 33, "-03:00")
62
+ @parser.send(:build_date, "20180507120000[0:GMT]").should == Time.gm(2018, 5, 7, 12)
63
+ @parser.send(:build_date, "20170904082855[-3:GMT]").should == Time.new(2017, 9, 4, 8, 28, 55, "-03:00")
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,50 @@
1
+ require "spec_helper"
2
+
3
+ describe OFX::Parser::OFX103 do
4
+ before do
5
+ @ofx = OFX::Parser::Base.new("spec/fixtures/v103.ofx")
6
+ @parser = @ofx.parser
7
+ end
8
+
9
+ it "should have a version" do
10
+ OFX::Parser::OFX103::VERSION.should == "1.0.3"
11
+ end
12
+
13
+ it "should set headers" do
14
+ @parser.headers.should == @ofx.headers
15
+ end
16
+
17
+ it "should trim trailing whitespace from headers" do
18
+ headers = OFX::Parser::OFX103.parse_headers("VERSION:103 ")
19
+ headers["VERSION"].should == "103"
20
+ end
21
+
22
+ it "should set body" do
23
+ @parser.body.should == @ofx.body
24
+ end
25
+
26
+ it "should set account" do
27
+ @parser.account.should be_a_kind_of(OFX::Account)
28
+ end
29
+
30
+ it "should set account" do
31
+ @parser.sign_on.should be_a_kind_of(OFX::SignOn)
32
+ end
33
+
34
+ it "should set statements" do
35
+ @parser.statements.size.should == 1
36
+ @parser.statements.first.should be_a_kind_of(OFX::Statement)
37
+ end
38
+
39
+ it "should know about all transaction types" do
40
+ valid_types = [
41
+ 'CREDIT', 'DEBIT', 'INT', 'DIV', 'FEE', 'SRVCHG', 'DEP', 'ATM', 'POS', 'XFER',
42
+ 'CHECK', 'PAYMENT', 'CASH', 'DIRECTDEP', 'DIRECTDEBIT', 'REPEATPMT', 'OTHER'
43
+ ]
44
+ valid_types.sort.should == OFX::Parser::OFX103::TRANSACTION_TYPES.keys.sort
45
+
46
+ valid_types.each do |transaction_type|
47
+ transaction_type.downcase.to_sym.should equal OFX::Parser::OFX103::TRANSACTION_TYPES[transaction_type]
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ describe OFX::Parser::OFX211 do
4
+ before do
5
+ @ofx = OFX::Parser::Base.new("spec/fixtures/v211.ofx")
6
+ @parser = @ofx.parser
7
+ end
8
+
9
+ it "should have a version" do
10
+ OFX::Parser::OFX211::VERSION.should == "2.1.1"
11
+ end
12
+
13
+ it "should set headers" do
14
+ @parser.headers.should == @ofx.headers
15
+ end
16
+
17
+ it "should set body" do
18
+ @parser.body.should == @ofx.body
19
+ end
20
+
21
+ it "should set account" do
22
+ @parser.account.should be_a_kind_of(OFX::Account)
23
+ end
24
+
25
+ it "should set account" do
26
+ @parser.sign_on.should be_a_kind_of(OFX::SignOn)
27
+ end
28
+
29
+ it "should set accounts" do
30
+ @parser.accounts.size.should == 2
31
+ end
32
+
33
+ it "should set statements" do
34
+ @parser.statements.size.should == 2
35
+ @parser.statements.first.should be_a_kind_of(OFX::Statement)
36
+ end
37
+
38
+ context "transactions" do
39
+ # Test file contains only three transactions. Let's just check
40
+ # them all.
41
+ context "first" do
42
+ before do
43
+ @t = @parser.accounts[0].transactions[0]
44
+ end
45
+
46
+ it "should contain the correct values" do
47
+ @t.amount.should == BigDecimal('-80')
48
+ @t.fit_id.should == "219378"
49
+ @t.memo.should be_empty
50
+ @t.posted_at.should == Time.parse("2005-08-24 08:00:00 +0000")
51
+ @t.name.should == "FrogKick Scuba Gear"
52
+ end
53
+ end
54
+
55
+ context "second" do
56
+ before do
57
+ @t = @parser.accounts[1].transactions[0]
58
+ end
59
+
60
+ it "should contain the correct values" do
61
+ @t.amount.should == BigDecimal('-23')
62
+ @t.fit_id.should == "219867"
63
+ @t.memo.should be_empty
64
+ @t.posted_at.should == Time.parse("2005-08-11 08:00:00 +0000")
65
+ @t.name.should == "Interest Charge"
66
+ end
67
+ end
68
+
69
+ context "third" do
70
+ before do
71
+ @t = @parser.accounts[1].transactions[1]
72
+ end
73
+
74
+ it "should contain the correct values" do
75
+ @t.amount.should == BigDecimal('350')
76
+ @t.fit_id.should == "219868"
77
+ @t.memo.should be_empty
78
+ @t.posted_at.should == Time.parse("2005-08-11 08:00:00 +0000")
79
+ @t.name.should == "Payment - Thank You"
80
+ end
81
+ end
82
+ end
83
+ end
84
+
@@ -47,6 +47,18 @@ describe OFX::Parser do
47
47
  }.should raise_error(OFX::UnsupportedFileError)
48
48
  end
49
49
 
50
+ it "should use 211 parser to parse version 200 ofx files" do
51
+ OFX::Parser::OFX211.stub(:new).and_return('ofx-211-parser')
52
+ ofx = OFX::Parser::Base.new(ofx_2_example('200'))
53
+ ofx.parser.should == 'ofx-211-parser'
54
+ end
55
+
56
+ it "should use 211 parser to parse version 202 ofx files" do
57
+ OFX::Parser::OFX211.stub(:new).and_return('ofx-211-parser')
58
+ ofx = OFX::Parser::Base.new(ofx_2_example('202'))
59
+ ofx.parser.should == 'ofx-211-parser'
60
+ end
61
+
50
62
  describe "headers" do
51
63
  it "should have OFXHEADER" do
52
64
  @ofx.headers["OFXHEADER"].should == "100"
@@ -87,16 +99,25 @@ describe OFX::Parser do
87
99
  @ofx.headers.should have_key("NEWFILEUID")
88
100
  @ofx.headers["NEWFILEUID"].should be_nil
89
101
  end
90
-
102
+
91
103
  it "should parse headers with CR and without LF" do
92
104
  @ofx = OFX::Parser::Base.new(ofx_with_carriage_return)
93
105
  @ofx.headers.size.should be(9)
94
106
  end
95
107
  end
96
-
108
+
97
109
  def ofx_with_carriage_return
98
110
  header = %{OFXHEADER:100\rDATA:OFXSGML\rVERSION:102\rSECURITY:NONE\rENCODING:USASCII\rCHARSET:1252\rCOMPRESSION:NONE\rOLDFILEUID:NONE\rNEWFILEUID:NONE\r}
99
111
  body = open("spec/fixtures/sample.ofx").read.split(/<OFX>/, 2)[1]
100
112
  header + "<OFX>" + body
101
113
  end
102
- end
114
+
115
+ def ofx_2_example(version)
116
+ <<-EndOfx
117
+ <?xml version="1.0" encoding="US-ASCII"?>
118
+ <?OFX OFXHEADER="200" VERSION="#{version}" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>"
119
+ <OFX>
120
+ </OFX>
121
+ EndOfx
122
+ end
123
+ end
@@ -0,0 +1,27 @@
1
+ require "spec_helper"
2
+
3
+ describe OFX::SignOn do
4
+ before do
5
+ @ofx = OFX::Parser::Base.new("spec/fixtures/creditcard.ofx")
6
+ @parser = @ofx.parser
7
+ @sign_on = @parser.sign_on
8
+ end
9
+
10
+ describe "sign_on" do
11
+ it "should return language" do
12
+ @sign_on.language.should == "ENG"
13
+ end
14
+
15
+ it "should return Financial Institution ID" do
16
+ @sign_on.fi_id.should == "24909"
17
+ end
18
+
19
+ it "should return Financial Institution Name" do
20
+ @sign_on.fi_name.should == "Citigroup"
21
+ end
22
+
23
+ it "should return status" do
24
+ @sign_on.status.should be_a(OFX::Status)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,131 @@
1
+ require "spec_helper"
2
+
3
+ describe OFX::Statement do
4
+ let(:parser) { ofx.parser }
5
+ let(:statement) { parser.statements.first }
6
+
7
+ context "Bank Account" do
8
+ let(:ofx) { OFX::Parser::Base.new("spec/fixtures/sample.ofx") }
9
+
10
+ it "returns currency" do
11
+ statement.currency.should == "BRL"
12
+ end
13
+
14
+ it "returns start date" do
15
+ statement.start_date.should == Time.parse("2009-10-09 08:00:00 +0000")
16
+ end
17
+
18
+ it "returns end date" do
19
+ statement.end_date.should == Time.parse("2009-11-03 08:00:00 +0000")
20
+ end
21
+
22
+ it "returns account" do
23
+ statement.account.should be_a(OFX::Account)
24
+ statement.account.id.should == '03227113109'
25
+ statement.account.type.should == :checking
26
+ end
27
+
28
+ it "returns transactions" do
29
+ statement.transactions.should be_a(Array)
30
+ statement.transactions.size.should == 36
31
+ end
32
+
33
+ describe "balance" do
34
+ let(:balance) { statement.balance }
35
+
36
+ it "returns balance" do
37
+ balance.amount.should == BigDecimal('598.44')
38
+ end
39
+
40
+ it "returns balance in pennies" do
41
+ balance.amount_in_pennies.should == 59844
42
+ end
43
+
44
+ it "returns balance date" do
45
+ balance.posted_at.should == Time.parse("2009-11-01 00:00:00 +0000")
46
+ end
47
+ end
48
+
49
+ describe "available_balance" do
50
+ let(:available_balance) { statement.available_balance }
51
+
52
+ it "returns available balance" do
53
+ available_balance.amount.should == BigDecimal('1555.99')
54
+ end
55
+
56
+ it "returns available balance in pennies" do
57
+ available_balance.amount_in_pennies.should == 155599
58
+ end
59
+
60
+ it "returns available balance date" do
61
+ available_balance.posted_at.should == Time.parse("2009-11-01 00:00:00 +0000")
62
+ end
63
+
64
+ context "when AVAILBAL not found" do
65
+ let(:ofx) { OFX::Parser::Base.new("spec/fixtures/utf8.ofx") }
66
+
67
+ it "returns nil " do
68
+ available_balance.should be_nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ context "Credit Card" do
75
+ let(:ofx) { OFX::Parser::Base.new("spec/fixtures/creditcard.ofx") }
76
+
77
+ it "returns currency" do
78
+ statement.currency.should == "USD"
79
+ end
80
+
81
+ it "returns start date" do
82
+ statement.start_date.should == Time.parse("2007-05-09 12:00:00 +0000")
83
+ end
84
+
85
+ it "returns end date" do
86
+ statement.end_date.should == Time.parse("2007-06-08 12:00:00 +0000")
87
+ end
88
+
89
+ it "returns account" do
90
+ statement.account.should be_a(OFX::Account)
91
+ statement.account.id.should == 'XXXXXXXXXXXX1111'
92
+ end
93
+
94
+ it "returns transactions" do
95
+ statement.transactions.should be_a(Array)
96
+ statement.transactions.size.should == 3
97
+ end
98
+
99
+ describe "balance" do
100
+ let(:balance) { statement.balance }
101
+
102
+ it "returns balance" do
103
+ balance.amount.should == BigDecimal('-1111.01')
104
+ end
105
+
106
+ it "returns balance in pennies" do
107
+ balance.amount_in_pennies.should == -111101
108
+ end
109
+
110
+ it "returns balance date" do
111
+ balance.posted_at.should == Time.parse("2007-06-23 19:20:13 +0000")
112
+ end
113
+ end
114
+
115
+ describe "available_balance" do
116
+ let(:available_balance) { statement.available_balance }
117
+
118
+ it "returns available balance" do
119
+ available_balance.amount.should == BigDecimal('19000.99')
120
+ end
121
+
122
+ it "returns available balance in pennies" do
123
+ available_balance.amount_in_pennies.should == 1900099
124
+ end
125
+
126
+ it "returns available balance date" do
127
+ available_balance.posted_at.should == Time.parse("2007-06-23 19:20:13 +0000")
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+
3
+ describe OFX::Status do
4
+ let(:ofx) { OFX::Parser::Base.new(ofx_file) }
5
+ let(:parser) { ofx.parser }
6
+ let(:status) { parser.sign_on.status }
7
+
8
+ context "success" do
9
+ let(:ofx_file) { "spec/fixtures/creditcard.ofx" }
10
+
11
+ it "should return code" do
12
+ status.code.should == 0
13
+ end
14
+
15
+ it "should return severity" do
16
+ status.severity.should == :info
17
+ end
18
+
19
+ it "should return message" do
20
+ status.message.should == ""
21
+ end
22
+
23
+ it "should be successful" do
24
+ status.success?.should == true
25
+ end
26
+ end
27
+
28
+ context "error" do
29
+ let(:ofx_file) { "spec/fixtures/error.ofx" }
30
+
31
+ it "should return code" do
32
+ status.code.should == 2000
33
+ end
34
+
35
+ it "should return severity" do
36
+ status.severity.should == :error
37
+ end
38
+
39
+ it "should return message" do
40
+ status.message.should == "We were unable to process your request. Please try again later."
41
+ end
42
+
43
+ it "should not be successful" do
44
+ status.success?.should == false
45
+ end
46
+ end
47
+ end