squeegee 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012 Kyle Welsby
1
+ Copyright (c) 2012 BritRuby LTD
2
2
 
3
3
  MIT License
4
4
 
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ module Squeegee
2
+ # Account
3
+ #
4
+ # Generic account with validations on specific parameters
5
+ class Account
6
+ attr_accessor :name, :amount, :due_at, :paid, :uid
7
+ def initialize(args={})
8
+ %w(name uid amount due_at).each do |key|
9
+ raise Squeegee::Error::InvalidParams,
10
+ "missing attribute `#{key}`" unless args.has_key?(key.to_sym)
11
+ end
12
+ @name = args[:name]
13
+ @amount = args[:amount]
14
+ @due_at = args[:due_at]
15
+ @paid = args[:paid]
16
+ @uid = args[:uid]
17
+ end
18
+ end
19
+ end
@@ -6,45 +6,9 @@ module Squeegee
6
6
  class BritishGas < Base
7
7
  HOST = "https://www.britishgas.co.uk"
8
8
  LOGIN_URL = "#{HOST}/Your_Account/Account_Details/"
9
- ACCOUNTS_URL = "#{HOST}/Account_History/Transactions_Account_List/"
9
+ ACCOUNTS_URL = "#{HOST}/AccountSummary/getAccountDetailsForSummary/"
10
10
  ACCOUNT_URL = "#{HOST}/Your_Account/Account_Transaction/"
11
11
 
12
- # British Gas Account information Extration
13
- # Example:
14
- # BritishGas::Account("8500", Mecanize.new)
15
- #
16
- class Account < BritishGas
17
- attr_accessor :paid, :due_at, :amount
18
-
19
- def initialize(id, agent)
20
- @agent = agent
21
- url = "#{Squeegee::BritishGas::ACCOUNT_URL}?accountnumber=#{id}"
22
- page = get(url)
23
- table = page.search("div#divHistoryTable table tbody")
24
- rows = table.search("tr").map do |row|
25
- tds = row.search("td")
26
- _row = {
27
- date: Date.parse(
28
- tds.first.inner_text.match(/\d{2}\s\w{3}\s\d{4}/)[0]
29
- ),
30
- type: tds[1].inner_text.match(/[A-Za-z]{2,}\s?[A-Za-z]?{2,}/)[0],
31
- debit: tds[2].inner_text.to_f,
32
- credit: tds[3].inner_text.to_f,
33
- balance: tds[4].inner_text.to_f
34
- }
35
- _row
36
- end
37
- @paid = !!(rows[0][:balance] = 0)
38
- rows.each do |row|
39
- if row[:debit] > 0
40
- @amount = row[:debit].to_s.gsub(/\.|,/,'').to_i
41
- @due_at = row[:date]
42
- break
43
- end
44
- end
45
- end
46
- end
47
-
48
12
  attr_accessor :accounts
49
13
 
50
14
  FIELD = {
@@ -58,9 +22,10 @@ module Squeegee
58
22
  params(args)
59
23
  @email = args.delete(:email)
60
24
  @password = args.delete(:password)
25
+ @accounts = []
61
26
 
62
27
  authenticate!
63
- get_statements
28
+ get_accounts
64
29
  end
65
30
 
66
31
  private
@@ -76,12 +41,45 @@ module Squeegee
76
41
  #raise Error::Unauthorized, "Account details could be wrong" if page.at('.error')
77
42
  end
78
43
 
79
- def get_statements
44
+ def get_accounts
80
45
  page = get(ACCOUNTS_URL)
81
- account_ids = page.search("table#tableSelectAccount td > strong").collect {|row| row.content.to_i}
82
- @accounts = account_ids.map do |account_id|
83
- Account.new(account_id, @agent)
46
+ accounts = JSON.parse(page.body)
47
+ #account_ids = page.search("table#tableSelectAccount td > strong").collect {|row| row.content.to_i}
48
+ accounts.each do |account|
49
+ response = get_account(account['accountReferenceNumber'])
50
+ @accounts << Squeegee::Account.new(response)
51
+ end
52
+ end
53
+
54
+ def get_account(id)
55
+ response = {}
56
+ url = "#{Squeegee::BritishGas::ACCOUNT_URL}?accountnumber=#{id}"
57
+ page = get(url)
58
+ table = page.search("div#divHistoryTable table tbody")
59
+ rows = table.search("tr").map do |row|
60
+ tds = row.search("td")
61
+ _row = {
62
+ date: Date.parse(
63
+ tds.first.inner_text.match(/\d{2}\s\w{3}\s\d{4}/)[0]
64
+ ),
65
+ type: tds[1].inner_text.match(/[A-Za-z]{2,}\s?[A-Za-z]?{2,}/)[0],
66
+ debit: tds[2].inner_text.to_f,
67
+ credit: tds[3].inner_text.to_f,
68
+ balance: tds[4].inner_text.to_f
69
+ }
70
+ _row
71
+ end
72
+ response[:paid] = !!(rows[0][:balance] = 0)
73
+ rows.each do |row|
74
+ if row[:debit] > 0
75
+ response[:amount] = row[:debit].to_s.gsub(/\.|,/,'').to_i
76
+ response[:due_at] = row[:date]
77
+ break
78
+ end
84
79
  end
80
+ response[:uid] = Digest::MD5.hexdigest("BritishGas#{id}")
81
+ response[:name] = "BritishGas (#{id.to_s[-4..-1]})"
82
+ response
85
83
  end
86
84
 
87
85
  end
@@ -11,7 +11,7 @@ module Squeegee
11
11
  password: 'password'
12
12
  }
13
13
 
14
- attr_accessor :due_at, :amount, :paid
14
+ attr_accessor :accounts
15
15
 
16
16
  def initialize(args = {})
17
17
  @keys = %w(username password)
@@ -20,6 +20,8 @@ module Squeegee
20
20
  @username = args.delete(:username)
21
21
  @password = args.delete(:password)
22
22
 
23
+ @accounts = []
24
+
23
25
  authenticate!
24
26
  get_statement
25
27
  end
@@ -38,24 +40,38 @@ module Squeegee
38
40
 
39
41
  def get_statement
40
42
  page = get(ACCOUNT_URL)
41
- amount = page.search(
43
+
44
+ account_id = page.search("#account_management_nav .account-number").
45
+ inner_text.match(/\d{4,}/)[0].to_i
46
+
47
+ amount_html = page.search(
42
48
  "#outstanding_balance_total span.money-left"
43
49
  ).inner_text.gsub(/\.|,/,'').match(/\d{1,}/)
44
50
 
45
- @amount = amount[0].to_i if amount
51
+ amount = amount_html[0].to_i if amount_html
46
52
 
47
- due_at = page.search(
53
+ due_at_html = page.search(
48
54
  "#outstanding_balance_box_label h5 span"
49
55
  ).inner_text.match(/(\d{2})\/(\d{2})\/(\d{2})/)
50
56
 
51
- @due_at = Date.parse("20#{due_at[3]}-#{due_at[2]}-#{due_at[1]}")if due_at
57
+ due_at = Date.parse("20#{due_at_html[3]}-#{due_at_html[2]}-#{due_at_html[1]}") if due_at_html
52
58
 
53
- @paid = page.search(
59
+ paid = page.search(
54
60
  "#payments .bill .desc"
55
61
  ).inner_text.downcase.include?("received")
56
62
 
57
- rescue NoMethodError => e
58
- raise Error::PageMissingContent, "Can't find something on the page"
63
+ uid = Digest::MD5.hexdigest("BSkyB#{account_id}")
64
+
65
+ @accounts << Squeegee::Account.new(
66
+ name: "Sky (#{account_id.to_s[-4..-1]})",
67
+ amount: amount,
68
+ due_at: due_at,
69
+ paid: paid,
70
+ uid: uid
71
+ )
72
+
73
+ #rescue NoMethodError => e
74
+ #raise Error::PageMissingContent, "Can't find something on the page"
59
75
  end
60
76
  end
61
77
  end
@@ -12,10 +12,11 @@ module Squeegee
12
12
  password: 'PASSWORD'
13
13
  }
14
14
 
15
- attr_accessor :paid, :amount, :due_at
15
+ attr_accessor :accounts, :account_id, :paid, :amount, :due_at
16
16
 
17
17
  def initialize(args = {})
18
18
  @keys = %w(username password)
19
+ @accounts = []
19
20
 
20
21
  params(args)
21
22
  @username = args.delete(:username)
@@ -33,6 +34,7 @@ module Squeegee
33
34
 
34
35
  form[FIELD[:username]] = @username
35
36
  form[FIELD[:password]] = @password
37
+
36
38
  page = @agent.submit(form, form.buttons.first)
37
39
 
38
40
  if page.uri == LOGIN_POST_URL && !page.search('.error').nil?
@@ -47,9 +49,15 @@ module Squeegee
47
49
 
48
50
  balance = page.search("#paymBalanceIncVAT").inner_text.gsub(/\.|,/,'').match(/\d{1,}/)
49
51
 
50
- @due_at = Date.parse(last_bill.search("td")[0].inner_text)
51
- @amount = last_bill.search('td')[2].inner_text.gsub(/\.|,/,'').match(/\d{1,}/)[0].to_i
52
+ due_at = Date.parse(last_bill.search("td")[0].inner_text)
53
+ amount = last_bill.search('td')[2].inner_text.gsub(/\.|,/,'').match(/\d{1,}/)[0].to_i
52
54
  #@paid = balance || balance[0].to_i >= 0
55
+ uid = Digest::MD5.hexdigest("OrangeUK#{@username}")
56
+
57
+ @accounts << Squeegee::Account.new(due_at: due_at,
58
+ name: "Orange UK",
59
+ uid: uid,
60
+ amount: amount)
53
61
  end
54
62
  end
55
63
  end
@@ -1,3 +1,3 @@
1
1
  module Squeegee
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/squeegee.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require 'mechanize'
2
2
  require 'logger'
3
+ require 'json'
3
4
  require 'squeegee/version'
4
5
  require 'squeegee/error'
5
6
  require 'squeegee/base'
7
+ require 'squeegee/account'
6
8
 
7
9
  require 'squeegee/british_gas'
8
10
  require 'squeegee/bskyb'
data/spec/spec_helper.rb CHANGED
@@ -9,8 +9,6 @@ require 'rspec'
9
9
  require 'webmock'
10
10
  require 'squeegee'
11
11
 
12
- CONFIGS = YAML::load(File.open('spec/support/configs.yml'))
13
-
14
12
  RSpec.configure do |config|
15
13
  config.order = :rand
16
14
  config.color_enabled = true
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Squeegee::Account do
4
+ let(:attr){{
5
+ name:'',
6
+ uid:'',
7
+ amount:'',
8
+ due_at:''
9
+ }}
10
+ subject {Squeegee::Account}
11
+ it {subject.new(attr).should respond_to(:name)}
12
+ it {subject.new(attr).should respond_to(:amount)}
13
+ it {subject.new(attr).should respond_to(:due_at)}
14
+ it {subject.new(attr).should respond_to(:paid)}
15
+
16
+ it "validates presence of name" do
17
+ attr.delete(:name)
18
+ expect{
19
+ subject.new(attr)
20
+ }.to raise_error(ArgumentError, "missing attribute `name`")
21
+ end
22
+
23
+ it "validates presence of amount" do
24
+ attr.delete(:amount)
25
+ expect{
26
+ subject.new(attr)
27
+ }.to raise_error(ArgumentError, "missing attribute `amount`")
28
+ end
29
+
30
+ it "validates presence of uid" do
31
+ attr.delete(:uid)
32
+ expect{
33
+ subject.new(attr)
34
+ }.to raise_error(ArgumentError, "missing attribute `uid`")
35
+ end
36
+
37
+ it "validates presence of due_at" do
38
+ attr.delete(:due_at)
39
+ expect{
40
+ subject.new(attr)
41
+ }.to raise_error(ArgumentError, "missing attribute `due_at`")
42
+ end
43
+ end
@@ -5,46 +5,30 @@ describe Squeegee::BritishGas do
5
5
  let(:node) {mock('node')}
6
6
  let(:form) {mock('form')}
7
7
  let(:button) {mock('button')}
8
+ let(:json) {[
9
+ {
10
+ 'accountReferenceNumber' => 850046061940,
11
+ 'Amount' => 70.00,
12
+ 'Paymenttype' => ""
13
+ }
14
+ ].to_json}
8
15
 
9
16
  subject {Squeegee::BritishGas}
10
17
 
11
- context "classes" do
12
18
  before do
13
- Mechanize.any_instance.stub(get: mechanize)
14
- end
15
- subject {Squeegee::BritishGas::Account.new(1, mechanize.as_null_object)}
16
- it "should get single account" do
17
- pending
18
- Mechanize.any_instance.should_receive(:get).at_least(:once).with(
19
- "https://www.britishgas.co.uk/Your_Account/Account_Transaction/?accountnumber=1"
20
- ).and_return(mechanize.as_null_object)
21
-
22
- subject
23
- end
24
- it "should build array of data" do
25
- mechanize.should_receive(:search).with(
26
- "div#divHistoryTable table tbody"
27
- ).and_return(node)
28
-
29
- node.should_receive(:search).with("tr").and_return([node])
30
- node.should_receive(:search).with("td").and_return(
31
- [
32
- stub(inner_text: "12 Feb 2012"),
33
- stub(inner_text: "Payment Received"),
34
- stub(inner_text: ""),
35
- stub(inner_text: "30.50"),
36
- stub(inner_text: "0.00")
37
- ]
38
- )
39
-
40
- subject.paid.should be_true
19
+ subject.any_instance.stub(:params)
20
+ subject.any_instance.stub(:authenticate!)
21
+ subject.any_instance.stub(:get_accounts)
22
+
23
+ Mechanize.stub(:new => mechanize.as_null_object)
24
+ mechanize.stub(:get => mechanize)
25
+
41
26
  end
42
- end
27
+
43
28
 
44
29
  context "Parameters" do
45
30
  before do
46
- subject.any_instance.stub(:authenticate!)
47
- subject.any_instance.stub(:get_statements)
31
+ subject.any_instance.unstub(:params)
48
32
  end
49
33
  it "raises InvalidParams when email is missing" do
50
34
  expect{
@@ -66,20 +50,15 @@ describe Squeegee::BritishGas do
66
50
  }.to_not raise_error
67
51
  end
68
52
  end
69
- context "calls" do
70
- before do
71
- subject.any_instance.stub(:params)
72
- subject.any_instance.stub(:authenticate!)
73
- subject.any_instance.stub(:get_statements)
74
- end
75
53
 
54
+ context "calls" do
76
55
  it "calls authenticate!" do
77
56
  subject.any_instance.should_receive(:authenticate!)
78
57
  subject.new
79
58
  end
80
59
 
81
60
  it "calls get_accounts" do
82
- subject.any_instance.should_receive(:get_statements)
61
+ subject.any_instance.should_receive(:get_accounts)
83
62
  subject.new
84
63
  end
85
64
 
@@ -90,66 +69,110 @@ describe Squeegee::BritishGas do
90
69
  end
91
70
  end
92
71
 
93
- context "Authentication" do
94
- before do
95
- subject.any_instance.stub(:params)
96
- #subject.any_instance.stub(get: mechanize.as_null_object)
97
- #Mechanize.any_instance.stub(get: mechanize.as_null_object)
98
- Mechanize.should_receive(:new).and_return(mechanize.as_null_object)
99
- mechanize.stub(form_with: form.as_null_object)
100
- end
101
- it "navigates to login URL" do
102
- mechanize.should_receive(:get).with(
103
- "https://www.britishgas.co.uk/Your_Account/Account_Details/"
104
- ).and_return(mechanize)
105
-
106
- subject.new({})
107
- end
108
-
109
- it "finds by form action" do
110
- mechanize.should_receive(:form_with).with(
111
- action: '/Online_User/Account_Summary/'
112
- ).and_return(form.as_null_object)
72
+ context "Private" do
73
+ describe "authenticate!" do
74
+ before do
75
+ subject.any_instance.unstub(:authenticate!)
76
+ #subject.any_instance.stub(get: mechanize.as_null_object)
77
+ #Mechanize.any_instance.stub(get: mechanize.as_null_object)
78
+ Mechanize.should_receive(:new).and_return(mechanize.as_null_object)
79
+ mechanize.stub(form_with: form.as_null_object)
80
+ end
81
+ it "navigates to login URL" do
82
+ mechanize.should_receive(:get).with(
83
+ "https://www.britishgas.co.uk/Your_Account/Account_Details/"
84
+ ).and_return(mechanize)
85
+
86
+ subject.new({})
87
+ end
88
+
89
+ it "finds by form action" do
90
+ mechanize.should_receive(:form_with).with(
91
+ action: '/Online_User/Account_Summary/'
92
+ ).and_return(form.as_null_object)
113
93
 
114
- subject.new
115
- end
116
-
117
- it "fills in form inputs" do
118
- form.should_receive(:[]=).with('userName', 'test@test.com')
119
- form.should_receive(:[]=).with('password', 'superduper')
120
-
121
- subject.new(email: "test@test.com", password: "superduper")
122
- end
123
-
124
- it "submits with first button" do
125
- form.should_receive(:buttons).and_return([button])
126
- mechanize.should_receive(:submit).with(form, button)
127
-
128
- subject.new(email: "test")
129
- end
130
- end
94
+ subject.new
95
+ end
131
96
 
132
- context "get_accounts" do
133
- before do
134
- subject.any_instance.stub(:params)
135
- Mechanize.any_instance.stub(get: mechanize)
136
- subject.any_instance.stub(:authenticate!)
137
- mechanize.stub(search: [stub(content: " 1 ")])
138
- subject::Account.stub(:new, mechanize)
139
- end
97
+ it "fills in form inputs" do
98
+ form.should_receive(:[]=).with('userName', 'test@test.com')
99
+ form.should_receive(:[]=).with('password', 'superduper')
140
100
 
141
- it "navigates to account list URL" do
142
- Mechanize.any_instance.should_receive(:get).with(
143
- "https://www.britishgas.co.uk/Account_History/Transactions_Account_List/"
144
- ).and_return(mechanize)
145
- subject.new
146
- end
101
+ subject.new(email: "test@test.com", password: "superduper")
102
+ end
103
+
104
+ it "submits with first button" do
105
+ form.should_receive(:buttons).and_return([button])
106
+ mechanize.should_receive(:submit).with(form, button)
107
+
108
+ subject.new(email: "test")
109
+ end
110
+ end
111
+
112
+ describe "get_accounts" do
113
+ before do
114
+ subject.any_instance.unstub(:get_accounts)
115
+ subject.any_instance.stub(:get_account)
116
+ Squeegee::Account.stub(:new)
117
+ end
118
+ it "finds account ID's" do
119
+ mechanize.should_receive(:body).and_return(json)
120
+ subject.any_instance.should_receive(:get_account).
121
+ with(850046061940)
122
+ subject.new
123
+ end
124
+ end
125
+
126
+ describe "get_account" do
127
+ let(:row) {stub(:row)}
128
+ let(:column) {stub(:column)}
129
+ before do
130
+ subject.any_instance.unstub(:get_accounts)
131
+ #subject.any_instance.unstub(:get_account)
132
+ mechanize.stub(:body).and_return(json)
133
+ mechanize.stub(:search).and_return(stub.as_null_object)
134
+ row.stub(:search).and_return(stub.as_null_object)
135
+ Squeegee::Account.stub(:new)
136
+ end
137
+
138
+ it "finds paid bill" do
139
+ mechanize.should_receive(:search).
140
+ with("div#divHistoryTable table tbody").
141
+ and_return(node)
142
+ node.should_receive(:search).
143
+ with('tr').
144
+ and_return([row])
145
+ row.should_receive(:search).
146
+ with('td').
147
+ and_return([
148
+ stub(inner_text: "12 Jun 2012"),
149
+ stub(inner_text: "Payment Received"),
150
+ stub(inner_text: "0.00"),
151
+ stub(inner_text: "10.00"),
152
+ stub(inner_text: "0.00")
153
+ ])
154
+ subject.new
155
+ end
156
+
157
+ it "finds debt" do
158
+ mechanize.should_receive(:search).
159
+ with("div#divHistoryTable table tbody").
160
+ and_return(node)
161
+ node.should_receive(:search).
162
+ with('tr').
163
+ and_return([row])
164
+ row.should_receive(:search).
165
+ with('td').
166
+ and_return([
167
+ stub(inner_text: "12 Jun 2012"),
168
+ stub(inner_text: "Debt"),
169
+ stub(inner_text: "20.00"),
170
+ stub(inner_text: "0.00"),
171
+ stub(inner_text: "20.00")
172
+ ])
173
+ subject.new
174
+ end
147
175
 
148
- it "initialises a new account" do
149
- pending
150
- #mechanize.stub(search: [stub(content: " 1 ")])
151
- #subject::Account.should_receive(:new).with(1, Mechanize.new())
152
- #subject.new
153
176
  end
154
177
  end
155
178
  end
@@ -87,22 +87,22 @@ describe Squeegee::BSkyB do
87
87
  mechanize.should_receive(:search).with(
88
88
  "#outstanding_balance_total span.money-left"
89
89
  ).and_return(node)
90
+ mechanize.should_receive(:search).with(
91
+ "#account_management_nav .account-number"
92
+ ).and_return(stub(:inner_text => "Account Number: 85000"))
90
93
  node.should_receive(:inner_text).and_return("£65.32")
91
94
  subject.new
92
95
  end
93
96
  it "finds the balance due date" do
94
- mechanize.should_receive(:search).with(
95
- "#outstanding_balance_total span.money-left"
96
- ).and_return(node)
97
+ mechanize.stub(:search => stub.as_null_object)
97
98
  mechanize.should_receive(:search).with(
98
99
  "#outstanding_balance_box_label h5 span"
99
100
  ).and_return(node)
100
- node.should_receive(:inner_text).twice.and_return("Payment due \r\n 13/03/12")
101
+ node.should_receive(:inner_text).and_return("Payment due \r\n 13/03/12")
101
102
  subject.new
102
103
  end
103
104
  it "finds the payment received" do
104
- mechanize.stub(:search => node)
105
- node.stub(:inner_text => "£62.58")
105
+ mechanize.stub(:search => stub.as_null_object)
106
106
 
107
107
  mechanize.should_receive(:search).with(
108
108
  '#payments .bill .desc'
@@ -113,6 +113,7 @@ describe Squeegee::BSkyB do
113
113
  end
114
114
 
115
115
  it "raises PageMissingContent error when something is not correct" do
116
+ pending "not implemented missing content rescue"
116
117
  mechanize.should_receive(:search).and_raise(NoMethodError)
117
118
  expect{
118
119
  subject.new
@@ -106,11 +106,12 @@ describe Squeegee::OrangeUK do
106
106
  stub(:inner_text => "£25.50")
107
107
  ]
108
108
  )
109
- orange = subject.new
110
- orange.amount.should be_a Integer
111
- orange.due_at.should be_a Date
112
- orange.amount.should eql 2550
113
- orange.due_at.should eql Date.parse('2012-05-15')
109
+ Squeegee::Account.should_receive(:new).
110
+ with(amount: 2550,
111
+ name: "Orange UK",
112
+ uid: "0a24082a818a019adfbe7d0b77d5448d",
113
+ due_at: Date.parse('2012-05-15'))
114
+ subject.new
114
115
  end
115
116
  end
116
117