dinero 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54db7e4b1d206d902c99a0bc1240c2e9f9c69cde
4
- data.tar.gz: 0e5c793a6055e095edd3849a91ddd7368fca5e48
3
+ metadata.gz: 00ee87276f3b118d80e13ae95262189b13f2f5ce
4
+ data.tar.gz: b9a357d02cc2517f326f7c15455713c3eacfb091
5
5
  SHA512:
6
- metadata.gz: 2794d5f6d5338f69d586e9a1b7ba146a6d597b6e6eeb52d4cc1df3e207200db5591888cd3965723b2f0423be30fbbb1617e7ca97f2c3ec33ed82fcde8ed406ac
7
- data.tar.gz: cce7bb0830d8644a4539d728dc882cca84e5ff7f082283f77027479b5fb32e4547a808684e6c52f880782808befaaec2a2a4cc2943f2a97f26a4f7dcbdcf4b9c
6
+ metadata.gz: fe0825fa56a8d1c86758200c3632b711b8b2e75e82ca3b86b526a4da2527f4672d55659f15300075ad5a061ee0531fc84b889657395d681eb8b3f02cf84ff22c
7
+ data.tar.gz: c2a802e4c94235d4669539b4abbc56bbe063fe05909dea0767b24a2e3ce087a554298dfae8417ba74b8ed05b1533b1e8b6be951d71f4d08ff3067836bcbbf41c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dinero (0.0.3)
4
+ dinero (0.0.4)
5
5
  nokogiri (~> 1.6.6)
6
6
  selenium-webdriver (~> 3.0)
7
7
 
data/README.md CHANGED
@@ -29,6 +29,7 @@ The following banks are implemented:
29
29
  * Capital One - https://capitalone.com (only U.S. credit card logins -- there's also banking, loans, investing, business, and Canada/UK credit cards)
30
30
  * Capital One 360 - https://capitalone360.com (formerly Ing Direct).
31
31
  * South State Bank - https://www.southstatebank.com/
32
+ * San Diego County Credit Union - https://www.sdccu.com/
32
33
 
33
34
  Currently, only Accounts balances are implemented. The following properties are available on each Account:
34
35
 
@@ -1,5 +1,6 @@
1
1
  module Dinero
2
2
  NUMERIC_REGEXP = /[\d|\-|\.]+/
3
+
3
4
  class Account
4
5
  attr_reader :account_type, :name, :name_other, :number, :balance, :available
5
6
  def initialize account_type, name, number, balance, available
@@ -10,6 +11,14 @@ module Dinero
10
11
  @number = number
11
12
  @balance = balance.scan(NUMERIC_REGEXP).join.to_f
12
13
  @available = available.scan(NUMERIC_REGEXP).join.to_f
14
+ @balance *= -1 if @account_type == :loan
15
+ end
16
+
17
+ %w(bank loan brokerage).each do |acct_type|
18
+ define_method "#{acct_type}_account?" do
19
+ self.account_type == acct_type.to_sym
20
+ end
13
21
  end
14
22
  end
23
+
15
24
  end
@@ -0,0 +1,116 @@
1
+ module Dinero
2
+ module Bank
3
+ # San Diego County Credit Union
4
+ class Sdccu < Base
5
+ LOGIN_URL = "https://internetbranch.sdccu.com/SDCCU/Login.aspx"
6
+ ACCOUNTS_SUMMARY_PATH = "/accounts"
7
+ CONNECTION_TIMEOUT = 10
8
+
9
+ def default_options
10
+ { timeout: CONNECTION_TIMEOUT, login_url: LOGIN_URL }
11
+ end
12
+
13
+ def post_username!
14
+ screenshot_on_error do
15
+ wait.until { connection.find_element(id: "ctlSignon_txtUserID") }
16
+ username_field = connection.find_element(id: "ctlSignon_txtUserID")
17
+ username_field.send_keys username
18
+
19
+ submit_button = connection.find_element(id: "ctlSignon_btnNext")
20
+ submit_button.click
21
+ end
22
+ end
23
+
24
+ def post_password!
25
+ screenshot_on_error do
26
+ wait.until { connection.find_element(id: "ctlSignon_txtPassword") }
27
+
28
+ password_field = connection.find_element(id: "ctlSignon_txtPassword")
29
+ password_field.send_keys password
30
+
31
+ login_btn = connection.find_element(id: "ctlSignon_btnLogin")
32
+ login_btn.click
33
+ end
34
+ end
35
+
36
+ def find_answer question
37
+ if q = security_questions.detect{ |qa| qa["question"] == question }
38
+ return q["answer"]
39
+ else
40
+ raise "Unknown security question: #{question.inspect}"
41
+ end
42
+ end
43
+
44
+ def post_security_answer!
45
+ return if on_accounts_summary_page?
46
+ screenshot_on_error do
47
+ wait.until { connection.find_element(id: "lblChallengeQuestion") }
48
+ question_text = connection.find_element(id: "lblChallengeQuestion").text
49
+ answer = find_answer question_text
50
+
51
+ answer_field = connection.find_element(id: "QuestionAnswer")
52
+ answer_field.send_keys answer
53
+
54
+ submit_button = logon_form.find_element(id:"btnSubmitAnswer")
55
+ submit_button.click
56
+ end
57
+ end
58
+
59
+ def post_credentials!
60
+ post_username!
61
+ post_password!
62
+ post_security_answer!
63
+ end
64
+
65
+ def after_successful_login
66
+ # the subdomain frequently changes, so capture the actual URL
67
+ # so we can return to the page if necessary.
68
+ @accounts_summary_url = connection.current_url
69
+ end
70
+
71
+ def on_accounts_summary_page?
72
+ connection.page_source =~ /Account Balances/
73
+ end
74
+
75
+ def goto_accounts_summary_page
76
+ return if authenticated? && on_accounts_summary_page?
77
+ authenticated? ? connection.navigate.to(@accounts_summary_url) : login!
78
+ end
79
+
80
+ def account_tables
81
+ accounts_summary_document.xpath("//div[@id='accountBalancesContainer_accountBalancesModule_accountList']//table")
82
+ end
83
+
84
+ def bank_accounts_table
85
+ account_tables[0]
86
+ end
87
+
88
+ def loan_accounts_table
89
+ account_tables[1]
90
+ end
91
+
92
+ def account_rows table, type
93
+ rows = table.xpath(".//tr").map{|m| m.xpath(".//td").map{|m| m.text.strip}}
94
+ rows.select{|s| s.size == 7}.map{|m| m.reject(&:empty?) << type}
95
+ end
96
+
97
+ def account_table_rows
98
+ account_rows(bank_accounts_table, :bank) + account_rows(loan_accounts_table, :loan)
99
+ end
100
+
101
+ # extract account data from the account summary page
102
+ def accounts
103
+ return @accounts if @accounts
104
+
105
+ @accounts = account_table_rows.map do |row|
106
+ acct_type = row.pop
107
+ number = row.shift
108
+ name = row.shift
109
+ balance = row.shift.scan(NUMERIC_REGEXP).join
110
+ available = acct_type == :loan ? "0.0" : balance
111
+ Account.new(acct_type, name, number, balance, available)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
data/lib/dinero/banks.rb CHANGED
@@ -30,9 +30,8 @@ module Dinero
30
30
 
31
31
  def establish_connection
32
32
  capabilities = Selenium::WebDriver::Remote::Capabilities.phantomjs(
33
- 'acceptSslCerts' => true,
34
33
  'phantomjs.page.settings.userAgent' => 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/33.0',
35
- 'service_args' => ['--ignore-ssl-errors=true']
34
+ 'service_args' => ['--ignore-ssl-errors=true', '--ssl-protocol=any']
36
35
  )
37
36
 
38
37
  driver = Selenium::WebDriver.for :phantomjs, :desired_capabilities => capabilities
@@ -1,3 +1,3 @@
1
1
  module Dinero
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/dinero.rb CHANGED
@@ -3,9 +3,12 @@ require 'nokogiri'
3
3
 
4
4
  require_relative 'dinero/version'
5
5
 
6
+ # Supported Banks
6
7
  require_relative 'dinero/banks'
7
8
  require_relative 'dinero/banks/capital_one'
8
9
  require_relative 'dinero/banks/capital_one_360'
9
10
  require_relative 'dinero/banks/south_state_bank'
11
+ require_relative 'dinero/banks/sdccu'
10
12
 
13
+ # Models
11
14
  require_relative 'dinero/account'
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ if bank_configured? :sdccu
4
+
5
+ RSpec.describe Dinero::Bank::Sdccu do
6
+ let(:bank_configuration) { bank_configurations[:sdccu] }
7
+ let(:account_types) { bank_configuration[:account_types].sort }
8
+ let(:accounts) { bank_configuration[:accounts] }
9
+
10
+ before(:all) do
11
+ VCR.use_cassette("accounts_sdccu", record: :new_episodes) do
12
+ @bank = Dinero::Bank::Sdccu.new(bank_configurations[:sdccu])
13
+ @bank.accounts
14
+ end
15
+ end
16
+
17
+ it "has security questions" do
18
+ expect(@bank.security_questions.count).to eq 4
19
+ end
20
+
21
+ it "finds favorite hobby answer" do
22
+ expect(@bank.find_answer("What is your favorite hobby?")).to eq "tennis"
23
+ end
24
+
25
+ it "posts credentials" do
26
+ expect(@bank.authenticated?).to be true
27
+ end
28
+
29
+ it "authenticates" do
30
+ @bank.login!
31
+ expect(@bank.authenticated?).to eq true
32
+ end
33
+
34
+ it "retrieves accounts_summary_document" do
35
+ expect(@bank.accounts_summary_document).to be_kind_of Nokogiri::HTML::Document
36
+ end
37
+
38
+ it "has account_tables" do
39
+ expect(@bank.account_tables.size).to eq 2
40
+ end
41
+
42
+ it "has bank_accounts_table" do
43
+ expect(@bank.bank_accounts_table).to be_a Nokogiri::XML::Element
44
+ end
45
+
46
+ it "has loan_accounts_table" do
47
+ expect(@bank.loan_accounts_table).to be_a Nokogiri::XML::Element
48
+ end
49
+
50
+ it "has 2 bank accounts" do
51
+ expect(@bank.account_rows(@bank.bank_accounts_table, :bank).size).to eq 2
52
+ end
53
+
54
+ it "has 1 loan account" do
55
+ expect(@bank.account_rows(@bank.loan_accounts_table, :loan).size).to eq 1
56
+ end
57
+
58
+ it "gets expected accounts" do
59
+ expect(@bank.accounts.size).to eq accounts
60
+ end
61
+
62
+ it "extracts account names" do
63
+ expect(@bank.accounts.map(&:name).select{|s| s =~ /Primary/}).to_not be_empty
64
+ end
65
+
66
+ it "extracts account numbers" do
67
+ expect(@bank.accounts.map(&:number).first).to eq "1"
68
+ end
69
+
70
+ it "expects balances to be greater than zero" do
71
+ expect(@bank.accounts.map(&:balance).any?(&:zero?)).to eq false
72
+ end
73
+
74
+ it "expects availables to be greater than zero for bank accts" do
75
+ expect(@bank.accounts.select{|s| s.bank_account?}.map(&:available).any?(&:zero?)).to eq false
76
+ end
77
+
78
+ it "expects availables to be zero for loan accts" do
79
+ expect(@bank.accounts.select{|s| s.loan_account?}.map(&:available).all?(&:zero?)).to eq true
80
+ end
81
+
82
+ it "sets account types" do
83
+ expect(@bank.accounts.map(&:account_type).uniq).to eq account_types
84
+ end
85
+ end
86
+
87
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dinero
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Lang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-30 00:00:00.000000000 Z
11
+ date: 2016-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -173,11 +173,13 @@ files:
173
173
  - lib/dinero/banks.rb
174
174
  - lib/dinero/banks/capital_one.rb
175
175
  - lib/dinero/banks/capital_one_360.rb
176
+ - lib/dinero/banks/sdccu.rb
176
177
  - lib/dinero/banks/south_state_bank.rb
177
178
  - lib/dinero/version.rb
178
179
  - log/.keep
179
180
  - spec/banks/capital_one_360_spec.rb
180
181
  - spec/banks/capital_one_spec.rb
182
+ - spec/banks/sdccu_spec.rb
181
183
  - spec/banks/south_state_bank_spec.rb
182
184
  - spec/fixtures/vcr_cassettes/.keep
183
185
  - spec/spec_helper.rb
@@ -210,6 +212,7 @@ summary: Dinero automates the process of logging into banking and financial webs
210
212
  test_files:
211
213
  - spec/banks/capital_one_360_spec.rb
212
214
  - spec/banks/capital_one_spec.rb
215
+ - spec/banks/sdccu_spec.rb
213
216
  - spec/banks/south_state_bank_spec.rb
214
217
  - spec/fixtures/vcr_cassettes/.keep
215
218
  - spec/spec_helper.rb