oanda_api_v20 1.5.0 → 2.0.0

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.
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