oanda_api_v20 1.5.0 → 2.0.0

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: b8108f8ae8240196afbf5ce81fb7cc96f9eeece1
4
- data.tar.gz: 97384a79da9a3a293529034eb5f2a483c5c9b96e
3
+ metadata.gz: 2e44f2d12b3c6e2fafe20137218ecfec9d8f4678
4
+ data.tar.gz: cec80bbcce9fe58398319d715a2d7a50cc1f37f4
5
5
  SHA512:
6
- metadata.gz: def31bfcd6716e880495a6396133334fd649c9fa64f42c1b957b4a165bb7b3b3ea74e13be95b3293ababb1f754ad935bd09ab24360ee9a58008e646bd61279f7
7
- data.tar.gz: 6ee7cb2047dd8e05eae5da2da3efd859a6dfad1fd1c4f989342b73a9a67e6bd43d8b6145991e1c73ab0c82e6d61a7e94a2ae7679d049af52e0a4a6855c496c1a
6
+ metadata.gz: 3b4439bf716d67a9117036009817ea19caa302b610b234832b7f7294116df3ab6b5ee6763967c6f4932a0630143367bcf498132f0b689e0c7627f9afdeff6a4e
7
+ data.tar.gz: 984932b04c7095c02af46a3000a6b2c8935f8062e707d235a45d07afcc43a4f94d719744d83b7277ab64e90525f1e3086982134b6e2ea58c001714bc717d694b
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
1
  .byebug_history
2
2
  oanda_api_v20-*.gem
3
3
  Gemfile.lock
4
+ .DS_Store
@@ -1,3 +1,3 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.2
3
+ - 2.3
@@ -1,5 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## 2.0.0
4
+ #### 2018-04-24
5
+ * Fixed issues when trying to reuse a Client object to make HTTP requests to Oanda.
6
+ * Moved instance variables last_action, last_arguments, instrument and account_id from the Client class to the Api class. They should not be part of a Client object.
7
+ * Removed last_transaction_id instance variable.
8
+ * RubyVM::Logger changed to ::Logger.
9
+ * Added a connection_pool_size option to allow persistent HTTP connection control on the Client object.
10
+ * Added a max_requests_per_second option to allow customized control on the Client max requests per second allowed to Oanda API.
11
+ * Added multithreading support for HTTP request governing. HTTP requests will be correctly allocated across multiple client threads.
12
+ * Raises an OandaApiV20::ApiError exception when no client object was supplied when instantiating an OandaApiV20::Api instance.
13
+
3
14
  ## 1.5.0
4
15
  #### 2017-07-07
5
16
  * Updated the orders method to allow query options to be passed along.
data/README.md CHANGED
@@ -37,6 +37,14 @@ If you need your requests to go through a proxy:
37
37
 
38
38
  client = OandaApiV20.new(access_token: 'my_access_token', proxy_url: 'https://user:pass@proxy.com:80')
39
39
 
40
+ You can adjust the persistend connection pool size, the default is 2:
41
+
42
+ client = OandaApiV20.new(access_token: 'my_access_token', connection_pool_size: 10)
43
+
44
+ You can adjust the number of requests per second allowed to Oanda API, the default is 100:
45
+
46
+ client = OandaApiV20.new(access_token: 'my_access_token', max_requests_per_second: 10)
47
+
40
48
  ## Examples
41
49
 
42
50
  ### Accounts
@@ -63,10 +71,6 @@ client.account('account_id').instruments.show
63
71
  client.account('account_id').instruments('EUR_USD,EUR_CAD').show
64
72
  ```
65
73
 
66
- ```ruby
67
- client.account('account_id').changes.show
68
- ```
69
-
70
74
  ```ruby
71
75
  options = { 'sinceTransactionID' => '6358' }
72
76
 
@@ -103,6 +107,10 @@ options = { 'instrument' => 'USD_CAD' }
103
107
  client.account('account_id').orders(options).show
104
108
  ```
105
109
 
110
+ ```ruby
111
+ client.account('account_id').pending_orders.show
112
+ ```
113
+
106
114
  ```ruby
107
115
  id = client.account('account_id').orders.show['orders'][0]['id']
108
116
 
@@ -128,10 +136,12 @@ id = client.account('account_id').orders.show['orders'][0]['id']
128
136
 
129
137
  options = {
130
138
  'order' => {
139
+ 'instrument' => 'EUR_CAD',
140
+ 'price' => '1.6000',
131
141
  'timeInForce' => 'GTC',
132
- 'price' => '1.7000',
133
- 'type' => 'TAKE_PROFIT',
134
- 'tradeID' => '1'
142
+ 'type' => 'MARKET_IF_TOUCHED',
143
+ 'units' => '200',
144
+ 'positionFill' => 'DEFAULT'
135
145
  }
136
146
  }
137
147
 
@@ -182,11 +192,11 @@ id = client.account('account_id').open_trades.show['trades'][0]['id']
182
192
  options = {
183
193
  'takeProfit' => {
184
194
  'timeInForce' => 'GTC',
185
- 'price' => '0.5'
195
+ 'price' => '2.5'
186
196
  },
187
197
  'stopLoss' => {
188
198
  'timeInForce' => 'GTC',
189
- 'price' => '2.5'
199
+ 'price' => '0.5'
190
200
  }
191
201
  }
192
202
 
@@ -25,7 +25,7 @@ module OandaApiV20
25
25
 
26
26
  # GET /v3/accounts/:account_id/changes
27
27
  def changes(options = {})
28
- options = { 'sinceTransactionID' => last_transaction_id } unless options['sinceTransactionID']
28
+ options = { 'sinceTransactionID' => nil } unless options['sinceTransactionID']
29
29
  Client.send(http_verb, "#{base_uri}/accounts/#{account_id}/changes", headers: headers, query: options)
30
30
  end
31
31
 
@@ -8,12 +8,89 @@ module OandaApiV20
8
8
  include Transactions
9
9
  include Pricing
10
10
 
11
- attr_accessor :http_verb, :base_uri, :headers, :account_id, :instrument, :last_transaction_id
11
+ attr_accessor :client, :base_uri, :headers, :account_id, :last_action, :last_arguments
12
+ attr_writer :instrument
12
13
 
13
14
  def initialize(options = {})
14
15
  options.each do |key, value|
15
16
  self.send("#{key}=", value) if self.respond_to?("#{key}=")
16
17
  end
18
+
19
+ raise OandaApiV20::ApiError, 'No client object was supplid.' unless client
20
+ @base_uri ||= client.base_uri
21
+ @headers ||= client.headers
22
+ end
23
+
24
+ class << self
25
+ def api_methods
26
+ Accounts.instance_methods + Instruments.instance_methods + Orders.instance_methods + Trades.instance_methods + Positions.instance_methods + Transactions.instance_methods + Pricing.instance_methods
27
+ end
28
+ end
29
+
30
+ self.api_methods.each do |method_name|
31
+ original_method = instance_method(method_name)
32
+
33
+ define_method(method_name) do |*args, &block|
34
+ # Add the block below before each of the api_methods to set the last_action and last_arguments.
35
+ # Return the OandaApiV20::Api object to allow for method chaining when any of the api_methods have been called.
36
+ # Only make an HTTP request to Oanda API When an action method like show, update, cancel, close or create was called.
37
+ set_last_action_and_arguments(method_name, *args)
38
+ return self unless http_verb
39
+
40
+ original_method.bind(self).call(*args, &block)
41
+ end
42
+ end
43
+
44
+ def method_missing(name, *args, &block)
45
+ case name
46
+ when :show, :create, :update, :cancel, :close
47
+ set_http_verb(name, last_action)
48
+
49
+ if respond_to?(last_action)
50
+ api_result = {}
51
+ client.update_last_api_request_at
52
+ client.govern_api_request_rate
53
+
54
+ begin
55
+ response = Http::Exceptions.wrap_and_check do
56
+ last_arguments.nil? || last_arguments.empty? ? send(last_action, &block) : send(last_action, *last_arguments, &block)
57
+ end
58
+ rescue Http::Exceptions::HttpException => e
59
+ raise OandaApiV20::RequestError, e.message
60
+ end
61
+
62
+ if response.body && !response.body.empty?
63
+ api_result.merge!(JSON.parse(response.body))
64
+ end
65
+ end
66
+
67
+ self.http_verb = nil
68
+ api_result
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ attr_accessor :http_verb
77
+
78
+ def set_last_action_and_arguments(action, *args)
79
+ self.last_action = action.to_sym
80
+ self.last_arguments = args
81
+ end
82
+
83
+ def set_http_verb(action, last_action)
84
+ case action
85
+ when :show
86
+ self.http_verb = :get
87
+ when :update, :cancel, :close
88
+ [:configuration].include?(last_action) ? self.http_verb = :patch : self.http_verb = :put
89
+ when :create
90
+ self.http_verb = :post
91
+ else
92
+ self.http_verb = nil
93
+ end
17
94
  end
18
95
  end
19
96
  end
@@ -2,14 +2,12 @@ module OandaApiV20
2
2
  class Client
3
3
  include HTTParty
4
4
 
5
- MAX_REQUESTS_PER_SECOND_ALLOWED = 30
6
-
7
5
  BASE_URI = {
8
6
  live: 'https://api-fxtrade.oanda.com/v3',
9
7
  practice: 'https://api-fxpractice.oanda.com/v3'
10
8
  }
11
9
 
12
- attr_accessor :access_token, :proxy_url
10
+ attr_accessor :access_token, :proxy_url, :max_requests_per_second, :connection_pool_size, :debug
13
11
  attr_reader :base_uri, :headers
14
12
 
15
13
  def initialize(options = {})
@@ -17,11 +15,14 @@ module OandaApiV20
17
15
  self.send("#{key}=", value) if self.respond_to?("#{key}=")
18
16
  end
19
17
 
20
- @debug = options[:debug] || false
21
- @last_api_request_at = Array.new(MAX_REQUESTS_PER_SECOND_ALLOWED)
22
- @base_uri = options[:practice] == true ? BASE_URI[:practice] : BASE_URI[:live]
18
+ @mutex = Mutex.new
19
+ @debug ||= false
20
+ @connection_pool_size ||= 2
21
+ @max_requests_per_second ||= 100
22
+ @last_api_request_at = Array.new(max_requests_per_second)
23
+ @base_uri = options[:practice] == true ? BASE_URI[:practice] : BASE_URI[:live]
23
24
 
24
- @headers = {}
25
+ @headers = {}
25
26
  @headers['Authorization'] = "Bearer #{access_token}"
26
27
  @headers['X-Accept-Datetime-Format'] = 'RFC3339'
27
28
  @headers['Content-Type'] = 'application/json'
@@ -35,113 +36,45 @@ module OandaApiV20
35
36
  keep_alive: 30,
36
37
  idle_timeout: 10,
37
38
  warn_timeout: 2,
38
- pool_size: 2
39
+ pool_size: connection_pool_size
39
40
  }
40
- persistent_connection_adapter_options.merge!(logger: RubyVM::Logger.new(STDOUT)) if @debug
41
+
42
+ persistent_connection_adapter_options.merge!(logger: ::Logger.new(STDOUT)) if debug
41
43
  Client.persistent_connection_adapter(persistent_connection_adapter_options)
42
44
  end
43
45
 
44
46
  def method_missing(name, *args, &block)
45
47
  case name
46
- when :show, :create, :update, :cancel, :close
47
- set_http_verb(name, last_action)
48
- api = Api.new(api_attributes)
49
-
50
- if api.respond_to?(last_action)
51
- api_result = {}
52
- set_last_api_request_at
53
- govern_api_request_rate
54
-
55
- begin
56
- response = Http::Exceptions.wrap_and_check do
57
- last_arguments.nil? || last_arguments.empty? ? api.send(last_action, &block) : api.send(last_action, *last_arguments, &block)
58
- end
59
- rescue Http::Exceptions::HttpException => e
60
- raise OandaApiV20::RequestError, e.message
61
- end
48
+ when *Api.api_methods
49
+ api_attributes = {
50
+ client: self,
51
+ last_action: name,
52
+ last_arguments: args
53
+ }
62
54
 
63
- if response.body && !response.body.empty?
64
- api_result.merge!(JSON.parse(response.body))
65
- set_last_transaction_id(api_result['lastTransactionID']) if api_result['lastTransactionID']
66
- end
67
- end
55
+ api_attributes.merge!(account_id: args.first) if name == :account
56
+ api_attributes.merge!(instrument: args.first) if name == :instrument
68
57
 
69
- api_result
70
- when *api_methods
71
- set_last_action_and_arguments(name, args)
72
- set_account_id(args.first) if name == :account
73
- set_instrument(args.first) if name == :instrument
74
- self
58
+ Api.new(api_attributes)
75
59
  else
76
60
  super
77
61
  end
78
62
  end
79
63
 
80
- private
81
-
82
- attr_accessor :http_verb, :account_id, :instrument, :last_transaction_id, :last_action, :last_arguments, :last_api_request_at
83
-
84
- def api_methods
85
- Accounts.instance_methods + Instruments.instance_methods + Orders.instance_methods + Trades.instance_methods + Positions.instance_methods + Transactions.instance_methods + Pricing.instance_methods
86
- end
87
-
88
64
  def govern_api_request_rate
89
65
  return unless last_api_request_at[0]
90
- halt = 1 - (last_api_request_at[MAX_REQUESTS_PER_SECOND_ALLOWED - 1] - last_api_request_at[0])
66
+ halt = 1 - (last_api_request_at[max_requests_per_second - 1] - last_api_request_at[0])
91
67
  sleep halt if halt > 0
92
68
  end
93
69
 
94
- def set_last_api_request_at
95
- last_api_request_at.push(Time.now.utc).shift
96
- end
97
-
98
- def set_last_action_and_arguments(action, args)
99
- set_last_action(action)
100
- set_last_arguments(args)
101
- end
102
-
103
- def set_last_action(action)
104
- self.last_action = action
105
- end
106
-
107
- def set_last_arguments(args)
108
- self.last_arguments = args.nil? || args.empty? ? nil : args.flatten
109
- end
110
-
111
- def set_account_id(id)
112
- self.account_id = id
113
- end
114
-
115
- def set_instrument(instrument)
116
- self.instrument = instrument
117
- end
118
-
119
- def set_last_transaction_id(id)
120
- self.last_transaction_id = id
121
- end
122
-
123
- def set_http_verb(action, last_action)
124
- case action
125
- when :show
126
- self.http_verb = :get
127
- when :update, :cancel, :close
128
- [:configuration].include?(last_action) ? self.http_verb = :patch : self.http_verb = :put
129
- when :create
130
- self.http_verb = :post
131
- else
132
- self.http_verb = nil
70
+ def update_last_api_request_at
71
+ @mutex.synchronize do
72
+ last_api_request_at.push(Time.now.utc).shift
133
73
  end
134
74
  end
135
75
 
136
- def api_attributes
137
- {
138
- http_verb: http_verb,
139
- base_uri: base_uri,
140
- headers: headers,
141
- account_id: account_id,
142
- instrument: instrument,
143
- last_transaction_id: last_transaction_id
144
- }
145
- end
76
+ private
77
+
78
+ attr_accessor :last_api_request_at
146
79
  end
147
80
  end
@@ -1,3 +1,4 @@
1
1
  module OandaApiV20
2
+ class ApiError < RuntimeError; end
2
3
  class RequestError < RuntimeError; end
3
4
  end
@@ -1,7 +1,7 @@
1
1
  # @see http://developer.oanda.com/rest-live-v20/instrument-ep/
2
2
  module OandaApiV20
3
3
  module Instruments
4
- attr_accessor :instrument
4
+ attr_reader :instrument
5
5
 
6
6
  # GET /v3/instruments/:instrument/candles
7
7
  def candles(options = {})
@@ -1,3 +1,3 @@
1
1
  module OandaApiV20
2
- VERSION = '1.5.0'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  s.add_development_dependency 'rspec', '~> 3.4'
24
24
  s.add_development_dependency 'webmock', '~> 2.1'
25
25
  s.add_development_dependency 'timecop', '~> 0.8'
26
- s.add_development_dependency 'rake'
26
+ s.add_development_dependency 'rake', '~> 10.5'
27
27
 
28
28
  s.files = `git ls-files`.split("\n")
29
29
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
@@ -2,326 +2,505 @@ require 'spec_helper'
2
2
 
3
3
  describe OandaApiV20::Api do
4
4
  describe '#initialize' do
5
- it 'sets the http_verb attribute when supplied' do
6
- api = OandaApiV20::Api.new(http_verb: :post)
7
- expect(api.http_verb).to eq(:post)
5
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token') }
6
+
7
+ it 'sets the client attribute when supplied' do
8
+ api = OandaApiV20::Api.new(client: client)
9
+ expect(api.client).to eq(client)
10
+ end
11
+
12
+ it 'raises an OandaApiV20::ApiError exception when no client object was supplied' do
13
+ expect{ OandaApiV20::Api.new }.to raise_error(OandaApiV20::ApiError)
8
14
  end
9
15
 
10
16
  it 'sets the base_uri attribute when supplied' do
11
17
  url = 'https://api-fxpractice.oanda.com/v3'
12
- api = OandaApiV20::Api.new(base_uri: url)
18
+ api = OandaApiV20::Api.new(client: client, base_uri: url)
13
19
  expect(api.base_uri).to eq(url)
14
20
  end
15
21
 
22
+ it 'sets the default base_uri attribute when not supplied' do
23
+ api = OandaApiV20::Api.new(client: client)
24
+ expect(api.base_uri).to eq('https://api-fxtrade.oanda.com/v3')
25
+ end
26
+
16
27
  it 'sets the headers attribute when supplied' do
17
28
  headers = { 'Content-Type' => 'application/json', 'Connection' => 'keep-alive', 'Keep-Alive' => '30' }
18
- api = OandaApiV20::Api.new(headers: headers)
29
+ api = OandaApiV20::Api.new(client: client, headers: headers)
19
30
  expect(api.headers).to eq(headers)
20
31
  end
21
32
 
33
+ it 'sets the default headers attribute when not supplied' do
34
+ api = OandaApiV20::Api.new(client: client)
35
+ expect(api.headers).to eq({ 'Authorization' => 'Bearer my_access_token', 'X-Accept-Datetime-Format' => 'RFC3339', 'Content-Type' => 'application/json' })
36
+ end
37
+
22
38
  it 'sets the account_id attribute when supplied' do
23
39
  account_id = '100-100-100'
24
- api = OandaApiV20::Api.new(account_id: account_id)
40
+ api = OandaApiV20::Api.new(client: client, account_id: account_id)
25
41
  expect(api.account_id).to eq(account_id)
26
42
  end
27
43
 
28
- it 'sets the last_transaction_id attribute when supplied' do
29
- last_transaction_id = '1'
30
- api = OandaApiV20::Api.new(last_transaction_id: last_transaction_id)
31
- expect(api.last_transaction_id).to eq(last_transaction_id)
32
- end
33
- end
34
-
35
- describe '#public_methods' do
36
- let!(:api) { OandaApiV20::Api.new }
37
- let(:public_methods) { [
38
- :account, :accounts, :summary, :instruments, :changes, :configuration,
39
- :order, :orders, :pending_orders,
40
- :trade, :trades, :open_trades,
41
- :position, :positions, :open_positions,
42
- :transaction, :transactions, :transactions_id_range, :transactions_since_id,
43
- :pricing
44
- ] }
45
-
46
- it 'responds to all public methods' do
47
- public_methods.each do |public_method|
48
- expect(api.respond_to?(public_method)).to be_truthy
49
- end
50
- end
51
- end
52
-
53
- describe 'constructs the correct API URL under' do
54
- let!(:api) { OandaApiV20::Api.new(base_uri: 'https://api-fxtrade.oanda.com/v3', account_id: '100-100-100', headers: {}) }
55
-
56
- before(:each) do
57
- stub_request(:any, /https:\/\/api-fxtrade\.oanda\.com\/v3.*/)
58
- api.http_verb = :get
44
+ it 'sets the instrument variable when supplied' do
45
+ instrument = 'EUR_USD'
46
+ api = OandaApiV20::Api.new(client: client, instrument: instrument)
47
+ expect(api.instance_variable_get(:@instrument)).to eq(instrument)
59
48
  end
60
49
 
61
- context 'accounts for' do
62
- it 'retrieving an account' do
63
- api.account('100-100-100')
64
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100')).to have_been_made.once
65
- end
66
-
67
- it 'retrieving all accounts' do
68
- api.accounts
69
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts')).to have_been_made.once
70
- end
71
-
72
- it 'retrieving a summary' do
73
- api.summary
74
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/summary')).to have_been_made.once
75
- end
76
-
77
- it 'retrieving all instruments' do
78
- api.instruments
79
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/instruments')).to have_been_made.once
80
- end
81
-
82
- it 'retrieving an instrument' do
83
- api.instruments('EUR_USD')
84
- options = { 'instruments' => 'EUR_USD' }
85
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/instruments').with(query: options)).to have_been_made.once
86
- end
87
-
88
- it 'retrieving all changes' do
89
- api.last_transaction_id = '1'
90
- api.changes
91
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/changes').with(query: { 'sinceTransactionID' => '1' })).to have_been_made.once
92
- end
93
-
94
- it 'retrieving all changes since a transaction id' do
95
- options = {
96
- 'sinceTransactionID' => '1'
97
- }
98
- api.changes(options)
99
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/changes').with(query: options)).to have_been_made.once
100
- end
101
-
102
- it 'updating a configuration' do
103
- api.http_verb = :patch
104
- options = { 'alias' => 'Timmy!' }
105
- api.configuration(options)
106
- expect(a_request(:patch, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/configuration').with(body: options.to_json))
107
- end
50
+ it 'sets the last_action when supplied' do
51
+ api = OandaApiV20::Api.new(client: client, last_action: 'accounts')
52
+ expect(api.last_action).to eq('accounts')
108
53
  end
109
54
 
110
- context 'instruments for' do
111
- let!(:api) { OandaApiV20::Api.new(base_uri: 'https://api-fxtrade.oanda.com/v3', account_id: '100-100-100', instrument: 'EUR_USD', headers: {}) }
112
-
113
- it 'retrieving candlestick data' do
114
- options = { 'count' => '10' }
115
- api.candles(options)
116
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles').with(query: options)).to have_been_made.once
117
- end
55
+ it 'sets the last_arguments when supplied' do
56
+ api = OandaApiV20::Api.new(client: client, last_action: 'account', last_arguments: ['100-100-100'])
57
+ expect(api.last_action).to eq('account')
58
+ expect(api.last_arguments).to eq(['100-100-100'])
118
59
  end
60
+ end
119
61
 
120
- context 'orders for' do
121
- it 'retrieving an order' do
122
- api.order('1')
123
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1')).to have_been_made.once
124
- end
125
-
126
- it 'creating an order' do
127
- api.http_verb = :post
128
- options = {
129
- 'order' => {
130
- 'units' => '100',
131
- 'instrument' => 'EUR_CAD',
132
- 'timeInForce' => 'FOK',
133
- 'type' => 'MARKET',
134
- 'positionFill' => 'DEFAULT'
62
+ describe '#method_missing' do
63
+ describe 'constructs the correct API URL under' do
64
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token', base_uri: 'https://api-fxtrade.oanda.com/v3', headers: {}) }
65
+ let!(:api) { OandaApiV20::Api.new(client: client, account_id: '100-100-100') }
66
+
67
+ before(:each) do
68
+ stub_request(:get, /https:\/\/api-fxtrade\.oanda\.com\/v3.*/)
69
+ end
70
+
71
+ context 'accounts for' do
72
+ it 'retrieving an account' do
73
+ api.account('100-100-100').show
74
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100')).to have_been_made.once
75
+ end
76
+
77
+ it 'retrieving all accounts' do
78
+ api.accounts.show
79
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts')).to have_been_made.once
80
+ end
81
+
82
+ it 'retrieving a summary' do
83
+ api.summary.show
84
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/summary')).to have_been_made.once
85
+ end
86
+
87
+ it 'retrieving all instruments' do
88
+ api.instruments.show
89
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/instruments')).to have_been_made.once
90
+ end
91
+
92
+ it 'retrieving an instrument' do
93
+ api.instruments('EUR_USD').show
94
+ options = { 'instruments' => 'EUR_USD' }
95
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/instruments').with(query: options)).to have_been_made.once
96
+ end
97
+
98
+ it 'retrieving no changes' do
99
+ options = {}
100
+ api.changes(options).show
101
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/changes').with(query: { 'sinceTransactionID' => '' })).to have_been_made.once
102
+ end
103
+
104
+ it 'retrieving all changes since a transaction ID' do
105
+ options = { 'sinceTransactionID' => '1' }
106
+ api.changes(options).show
107
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/changes').with(query: options)).to have_been_made.once
108
+ end
109
+
110
+ it 'updating a configuration' do
111
+ options = { 'alias' => 'Timmy!' }
112
+ request = stub_request(:patch, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/configuration').with(body: options)
113
+ api.configuration(options).update
114
+ expect(request).to have_been_requested.once
115
+ end
116
+ end
117
+
118
+ context 'instruments for' do
119
+ let!(:api) { OandaApiV20::Api.new(client: client, account_id: '100-100-100', instrument: 'EUR_USD') }
120
+
121
+ it 'retrieving candlestick data' do
122
+ options = { 'count' => '10' }
123
+ api.candles(options).show
124
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/instruments/EUR_USD/candles').with(query: options)).to have_been_made.once
125
+ end
126
+ end
127
+
128
+ context 'orders for' do
129
+ it 'retrieving an order' do
130
+ api.order('1').show
131
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1')).to have_been_made.once
132
+ end
133
+
134
+ it 'creating an order' do
135
+ options = {
136
+ 'order' => {
137
+ 'units' => '100',
138
+ 'instrument' => 'EUR_CAD',
139
+ 'timeInForce' => 'FOK',
140
+ 'type' => 'MARKET',
141
+ 'positionFill' => 'DEFAULT'
142
+ }
135
143
  }
136
- }
137
- api.order(options)
138
- expect(a_request(:post, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders').with(body: options.to_json)).to have_been_made.once
139
- end
144
+ request = stub_request(:post, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders').with(body: options)
145
+ api.order(options).create
146
+ expect(request).to have_been_requested.once
147
+ end
148
+
149
+ it 'updating an order' do
150
+ options = {
151
+ 'order' => {
152
+ 'timeInForce' => 'GTC',
153
+ 'price' => '1.7000',
154
+ 'type' => 'TAKE_PROFIT',
155
+ 'tradeID' => '1'
156
+ }
157
+ }
158
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1').with(body: options)
159
+ api.order('1', options).update
160
+ expect(request).to have_been_requested.once
161
+ end
162
+
163
+ it 'updating an order client extensions' do
164
+ options = {
165
+ 'clientExtensions' => {
166
+ 'comment' => 'New comment for my limit order'
167
+ }
168
+ }
169
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1/clientExtensions').with(body: options)
170
+ api.order('1', options).update
171
+ expect(request).to have_been_requested.once
172
+ end
173
+
174
+ it 'cancelling an order' do
175
+ request = stub_request(:put,'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1/cancel')
176
+ api.order('1').cancel
177
+ expect(request).to have_been_requested.once
178
+ end
179
+
180
+ it 'retrieving all orders' do
181
+ api.orders.show
182
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders')).to have_been_made.once
183
+ end
184
+
185
+ it 'retrieving all orders' do
186
+ options = { 'instrument' => 'USD_CAD' }
187
+ api.orders(options).show
188
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders').with(query: options)).to have_been_made.once
189
+ end
190
+
191
+ it 'retrieving all pending orders' do
192
+ api.pending_orders.show
193
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/pendingOrders')).to have_been_made.once
194
+ end
195
+ end
196
+
197
+ context 'trades for' do
198
+ it 'retrieving a trade' do
199
+ api.trade('1').show
200
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1')).to have_been_made.once
201
+ end
202
+
203
+ it 'updating a trade' do
204
+ options = {
205
+ 'takeProfit' => {
206
+ 'timeInForce' => 'GTC',
207
+ 'price' => '0.5'
208
+ },
209
+ 'stopLoss' => {
210
+ 'timeInForce' => 'GTC',
211
+ 'price' => '2.5'
212
+ }
213
+ }
214
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/orders').with(body: options)
215
+ api.trade('1', options).update
216
+ expect(request).to have_been_requested.once
217
+ end
218
+
219
+ it 'updating a trade client extensions' do
220
+ options = {
221
+ 'clientExtensions' => {
222
+ 'comment' => 'This is a USD/CAD trade',
223
+ 'tag' => 'trade tag',
224
+ 'id' => 'my_usd_cad_trade'
225
+ }
226
+ }
227
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/clientExtensions').with(body: options)
228
+ api.trade('1', options).update
229
+ expect(request).to have_been_requested.once
230
+ end
231
+
232
+ it 'closing a trade' do
233
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/close')
234
+ api.trade('1').close
235
+ expect(request).to have_been_requested.once
236
+ end
237
+
238
+ it 'closing a trade partially' do
239
+ options = { 'units' => '10' }
240
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/close')
241
+ api.trade('1', options).close
242
+ expect(request).to have_been_requested.once
243
+ end
244
+
245
+ it 'retrieving all trades' do
246
+ options = { 'instrument' => 'USD_CAD' }
247
+ api.trades(options).show
248
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades').with(query: options)).to have_been_made.once
249
+ end
250
+
251
+ it 'retrieving all open trades' do
252
+ api.open_trades.show
253
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/openTrades')).to have_been_made.once
254
+ end
255
+ end
256
+
257
+ context 'positions for' do
258
+ it 'retrieving a position' do
259
+ api.position('EUR_USD').show
260
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_USD')).to have_been_made.once
261
+ end
262
+
263
+ it 'retrieving all positions' do
264
+ api.positions.show
265
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions')).to have_been_made.once
266
+ end
267
+
268
+ it 'retrieving all open positions' do
269
+ api.open_positions.show
270
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/openPositions')).to have_been_made.once
271
+ end
272
+
273
+ it 'closing a position' do
274
+ options = { 'longUnits' => 'ALL' }
275
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_CAD/close').with(body: options)
276
+ api.position('EUR_CAD', options).close
277
+ expect(request).to have_been_requested.once
278
+ end
279
+
280
+ it 'closing a position partially' do
281
+ options = { 'longUnits' => '99' }
282
+ request = stub_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_CAD/close').with(body: options)
283
+ api.position('EUR_CAD', options).close
284
+ expect(request).to have_been_requested.once
285
+ end
286
+ end
287
+
288
+ context 'transactions for' do
289
+ it 'retrieving a transaction' do
290
+ api.transaction('1').show
291
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/1')).to have_been_made.once
292
+ end
293
+
294
+ it 'retrieving all transactions' do
295
+ api.transactions.show
296
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions')).to have_been_made.once
297
+ end
298
+
299
+ it 'retrieving all transactions in date range' do
300
+ options = {
301
+ 'from' => '2016-08-01T02:00:00Z',
302
+ 'to' => '2016-08-15T02:00:00Z'
303
+ }
304
+ api.transactions(options).show
305
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions').with(query: options)).to have_been_made.once
306
+ end
307
+
308
+ it 'retrieving all transactions in an ID range' do
309
+ options = {
310
+ 'from' => '6409',
311
+ 'to' => '6412'
312
+ }
313
+ api.transactions_id_range(options).show
314
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/idrange').with(query: options)).to have_been_made.once
315
+ end
140
316
 
141
- it 'updating an order' do
142
- api.http_verb = :put
143
- options = {
144
- 'order' => {
145
- 'timeInForce' => 'GTC',
146
- 'price' => '1.7000',
147
- 'type' => 'TAKE_PROFIT',
148
- 'tradeID' => '1'
317
+ it 'retrieving all transactions since an ID' do
318
+ options = {
319
+ 'id' => '6411'
149
320
  }
150
- }
151
- api.order('1', options)
152
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1').with(body: options.to_json)).to have_been_made.once
321
+ api.transactions_since_id(options).show
322
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/sinceid').with(query: options)).to have_been_made.once
323
+ end
153
324
  end
154
325
 
155
- it 'updating an order client extensions' do
156
- api.http_verb = :put
157
- options = {
158
- 'clientExtensions' => {
159
- 'comment' => 'New comment for my limit order'
326
+ context 'pricing for' do
327
+ it 'retrieving all pricing' do
328
+ options = {
329
+ 'instruments' => 'EUR_USD,USD_CAD'
160
330
  }
161
- }
162
- api.order('1', options)
163
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1/clientExtensions').with(body: options.to_json)).to have_been_made.once
331
+ api.pricing(options).show
332
+ expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/pricing').with(query: options)).to have_been_made.once
333
+ end
164
334
  end
335
+ end
165
336
 
166
- it 'cancelling an order' do
167
- api.http_verb = :put
168
- api.order('1')
169
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders/1/cancel')).to have_been_made.once
170
- end
337
+ describe 'network' do
338
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token', base_uri: 'https://api-fxtrade.oanda.com/v3', headers: {}) }
339
+ let!(:api) { OandaApiV20::Api.new(client: client) }
171
340
 
172
- it 'retrieving all orders' do
173
- api.orders
174
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders')).to have_been_made.once
175
- end
341
+ let(:response_account) { '{"account":{"id":"100-100-100","NAV":"100000.0000","balance":"100000.0000","lastTransactionID":"99","orders":[],"positions":[],"trades":[],"pendingOrderCount":0},"lastTransactionID":"99"}' }
342
+ let!(:request_account) { stub_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100').to_return(status: 200, body: response_account, headers: {}) }
176
343
 
177
- it 'retrieving all orders' do
178
- options = { 'instrument' => 'USD_CAD' }
179
- api.orders(options)
180
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders').with(query: options)).to have_been_made.once
181
- end
344
+ let(:response_accounts) { '{"accounts":[{"id":"100-100-100","tags":[]}]}' }
345
+ let!(:request_accounts) { stub_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts').to_return(status: 200, body: response_accounts, headers: {}) }
182
346
 
183
- it 'retrieving all pending orders' do
184
- api.pending_orders
185
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/pendingOrders')).to have_been_made.once
347
+ it 'makes a request to Oanda API' do
348
+ api.accounts.show
349
+ expect(request_accounts).to have_been_requested
350
+ expect(request_accounts).to have_been_requested.at_most_once
186
351
  end
187
- end
188
352
 
189
- context 'trades for' do
190
- it 'retrieving a trade' do
191
- api.trade('1')
192
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1')).to have_been_made.once
353
+ it 'returns the response from Oanda API' do
354
+ expect(api.accounts.show).to eq(JSON.parse(response_accounts))
355
+ expect(api.account('100-100-100').show).to eq(JSON.parse(response_account))
193
356
  end
357
+ end
194
358
 
195
- it 'updating a trade' do
196
- api.http_verb = :put
197
- options = {
198
- 'takeProfit' => {
199
- 'timeInForce' => 'GTC',
200
- 'price' => '0.5'
201
- },
202
- 'stopLoss' => {
203
- 'timeInForce' => 'GTC',
204
- 'price' => '2.5'
359
+ describe 'sets the correct HTTP verb' do
360
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token', base_uri: 'https://api-fxtrade.oanda.com/v3', headers: {}) }
361
+ let!(:api) { OandaApiV20::Api.new(client: client, account_id: '100-100-100') }
362
+
363
+ context 'for GET' do
364
+ let!(:request) { stub_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts') }
365
+
366
+ it 'uses the correct HTTP verb' do
367
+ api.accounts.show
368
+ expect(request).to have_been_requested.once
369
+ end
370
+
371
+ it 'clears the HTTP verb attribute after use' do
372
+ api.accounts.show
373
+ expect(api.send(:http_verb)).to be_nil
374
+ end
375
+ end
376
+
377
+ context 'for POST' do
378
+ let!(:options) {
379
+ {
380
+ 'order' => {
381
+ 'units' => '100',
382
+ 'instrument' => 'EUR_CAD',
383
+ 'timeInForce' => 'FOK',
384
+ 'type' => 'MARKET',
385
+ 'positionFill' => 'DEFAULT'
386
+ }
205
387
  }
206
388
  }
207
- api.trade('1', options)
208
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/orders').with(body: options.to_json)).to have_been_made.once
209
- end
389
+ let!(:request) { stub_request(:post, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/orders').with(body: options) }
210
390
 
211
- it 'updating a trade client extensions' do
212
- api.http_verb = :put
213
- options = {
214
- 'clientExtensions' => {
215
- 'comment' => 'This is a USD/CAD trade',
216
- 'tag' => 'trade tag',
217
- 'id' => 'my_usd_cad_trade'
218
- }
219
- }
220
- api.trade('1', options)
221
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/clientExtensions').with(body: options.to_json)).to have_been_made.once
222
- end
391
+ it 'uses the correct HTTP verb' do
392
+ api.order(options).create
393
+ expect(request).to have_been_requested.once
394
+ end
223
395
 
224
- it 'closing a trade' do
225
- api.http_verb = :put
226
- api.trade('1')
227
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/close')).to have_been_made.once
396
+ it 'clears the HTTP verb attribute after use' do
397
+ api.order(options).create
398
+ expect(api.send(:http_verb)).to be_nil
399
+ end
228
400
  end
229
401
 
230
- it 'closing a trade partially' do
231
- api.http_verb = :put
232
- options = { 'units' => '10' }
233
- api.trade('1', options)
234
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades/1/close')).to have_been_made.once
235
- end
402
+ context 'for PATCH' do
403
+ let!(:options) { { 'alias' => 'Timmy!' } }
404
+ let!(:request) { stub_request(:patch, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/configuration').with(body: options) }
236
405
 
237
- it 'retrieving all trades' do
238
- options = { 'instrument' => 'USD_CAD' }
239
- api.trades(options)
240
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/trades').with(query: options)).to have_been_made.once
241
- end
406
+ it 'uses the correct HTTP verb' do
407
+ api.configuration(options).update
408
+ expect(request).to have_been_requested.once
409
+ end
242
410
 
243
- it 'retrieving all open trades' do
244
- api.open_trades
245
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/openTrades')).to have_been_made.once
411
+ it 'clears the HTTP verb attribute after use' do
412
+ api.configuration(options).update
413
+ expect(api.send(:http_verb)).to be_nil
414
+ end
246
415
  end
247
416
  end
417
+ end
248
418
 
249
- context 'positions for' do
250
- it 'retrieving a position' do
251
- api.position('EUR_USD')
252
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_USD')).to have_been_made.once
253
- end
254
-
255
- it 'retrieving all positions' do
256
- api.positions
257
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions')).to have_been_made.once
258
- end
259
-
260
- it 'retrieving all open positions' do
261
- api.open_positions
262
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/openPositions')).to have_been_made.once
263
- end
264
-
265
- it 'closing a position' do
266
- api.http_verb = :put
267
- options = { 'longUnits' => 'ALL' }
268
- api.position('EUR_CAD', options)
269
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_CAD/close').with(body: options.to_json)).to have_been_made.once
270
- end
419
+ describe 'public methods' do
420
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token') }
421
+ let!(:api) { OandaApiV20::Api.new(client: client) }
422
+ let(:public_methods) { [
423
+ :account, :accounts, :summary, :instruments, :changes, :configuration,
424
+ :order, :orders, :pending_orders,
425
+ :trade, :trades, :open_trades,
426
+ :position, :positions, :open_positions,
427
+ :transaction, :transactions, :transactions_id_range, :transactions_since_id,
428
+ :pricing,
429
+ :candles
430
+ ] }
271
431
 
272
- it 'closing a position partially' do
273
- api.http_verb = :put
274
- options = { 'longUnits' => '99' }
275
- api.position('EUR_CAD', options)
276
- expect(a_request(:put, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/positions/EUR_CAD/close').with(body: options.to_json)).to have_been_made.once
432
+ it 'responds to all public methods' do
433
+ public_methods.each do |public_method|
434
+ expect(api.respond_to?(public_method)).to be_truthy
277
435
  end
278
436
  end
279
437
 
280
- context 'transactions for' do
281
- it 'retrieving a transaction' do
282
- api.transaction('1')
283
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/1')).to have_been_made.once
284
- end
438
+ it 'returns an OandaApiV20::Api instance when calling any of the public methods' do
439
+ expect(api.accounts).to be_an_instance_of(OandaApiV20::Api)
440
+ end
285
441
 
286
- it 'retrieving all transactions' do
287
- api.transactions
288
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions')).to have_been_made.once
289
- end
442
+ it 'makes a request to Oanda API when calling any of the action methods' do
443
+ request = stub_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts')
444
+ api.accounts.show
445
+ expect(request).to have_been_requested.once
446
+ end
447
+ end
290
448
 
291
- it 'retrieving all transactions in date range' do
292
- options = {
293
- 'from' => '2016-08-01T02:00:00Z',
294
- 'to' => '2016-08-15T02:00:00Z'
295
- }
296
- api.transactions(options)
297
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions').with(query: options)).to have_been_made.once
449
+ describe 'private methods' do
450
+ describe '#set_http_verb' do
451
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token', base_uri: 'https://api-fxtrade.oanda.com/v3', headers: {}) }
452
+ let!(:api) { OandaApiV20::Api.new(client: client) }
453
+
454
+ describe 'sets the correct HTTP verb' do
455
+ it 'for GET' do
456
+ api.send(:set_http_verb, :show, nil)
457
+ expect(api.send(:http_verb)).to eq(:get)
458
+ end
459
+
460
+ it 'for POST' do
461
+ api.send(:set_http_verb, :create, nil)
462
+ expect(api.send(:http_verb)).to eq(:post)
463
+ end
464
+
465
+ it 'for PUT' do
466
+ api.send(:set_http_verb, :update, nil)
467
+ expect(api.send(:http_verb)).to eq(:put)
468
+ end
469
+
470
+ it 'for PUT' do
471
+ api.send(:set_http_verb, :cancel, nil)
472
+ expect(api.send(:http_verb)).to eq(:put)
473
+ end
474
+
475
+ it 'for PUT' do
476
+ api.send(:set_http_verb, :close, nil)
477
+ expect(api.send(:http_verb)).to eq(:put)
478
+ end
479
+
480
+ it 'for PATCH' do
481
+ api.send(:set_http_verb, :update, :configuration)
482
+ expect(api.send(:http_verb)).to eq(:patch)
483
+ end
484
+
485
+ it 'for POST' do
486
+ api.send(:set_http_verb, :create, nil)
487
+ expect(api.send(:http_verb)).to eq(:post)
488
+ end
298
489
  end
490
+ end
299
491
 
300
- it 'retrieving all transactions in an id range' do
301
- options = {
302
- 'from' => '6409',
303
- 'to' => '6412'
304
- }
305
- api.transactions_id_range(options)
306
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/idrange').with(query: options)).to have_been_made.once
307
- end
492
+ describe '#set_last_action_and_arguments' do
493
+ let!(:client) { OandaApiV20::Client.new(access_token: 'my_access_token', base_uri: 'https://api-fxtrade.oanda.com/v3', headers: {}) }
494
+ let!(:api) { OandaApiV20::Api.new(client: client) }
308
495
 
309
- it 'retrieving all transactions since an id' do
310
- options = {
311
- 'id' => '6411'
312
- }
313
- api.transactions_since_id(options)
314
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/transactions/sinceid').with(query: options)).to have_been_made.once
496
+ it 'sets the last_action attribute' do
497
+ api.send(:set_last_action_and_arguments, :accounts)
498
+ expect(api.send(:last_action)).to eq(:accounts)
315
499
  end
316
- end
317
500
 
318
- context 'pricing for' do
319
- it 'retrieving all pricing' do
320
- options = {
321
- 'instruments' => 'EUR_USD,USD_CAD'
322
- }
323
- api.pricing(options)
324
- expect(a_request(:get, 'https://api-fxtrade.oanda.com/v3/accounts/100-100-100/pricing').with(query: options)).to have_been_made.once
501
+ it 'sets the last_arguments attribute' do
502
+ api.send(:set_last_action_and_arguments, :account, '100-100-100')
503
+ expect(api.send(:last_arguments)).to eq(['100-100-100'])
325
504
  end
326
505
  end
327
506
  end