responsys-api 0.0.8 → 0.0.9

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.
Files changed (49) hide show
  1. checksums.yaml +8 -8
  2. data/.gitignore +3 -0
  3. data/.travis.yml +7 -0
  4. data/README.md +2 -2
  5. data/Rakefile +11 -0
  6. data/lib/responsys/api/campaign.rb +1 -1
  7. data/lib/responsys/api/client.rb +7 -10
  8. data/lib/responsys/api/object/email_format.rb +1 -1
  9. data/lib/responsys/api/object/field_type.rb +1 -1
  10. data/lib/responsys/api/object/optional_data.rb +1 -1
  11. data/lib/responsys/api/object/query_column.rb +1 -1
  12. data/lib/responsys/api/object/record.rb +1 -1
  13. data/lib/responsys/api/object/record_data.rb +1 -1
  14. data/lib/responsys/api/session.rb +16 -1
  15. data/lib/responsys/helper.rb +9 -1
  16. data/lib/responsys/i18n/en.yml +24 -19
  17. data/lib/responsys/i18n/fr.yml +21 -0
  18. data/lib/responsys_api.rb +1 -3
  19. data/responsys-api.gemspec +1 -1
  20. data/spec/api/campaign_spec.rb +3 -7
  21. data/spec/api/client_spec.rb +18 -48
  22. data/spec/api/list_spec.rb +7 -11
  23. data/spec/api/table_spec.rb +26 -31
  24. data/spec/api_credentials.sample.yml +3 -0
  25. data/spec/fixtures/vcr_cassettes/api/client/expired_session.yml +14 -953
  26. data/spec/fixtures/vcr_cassettes/api/list/merge.yml +9 -97
  27. data/spec/fixtures/vcr_cassettes/api/list/retrieve.yml +11 -11
  28. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single.yml +9 -97
  29. data/spec/fixtures/vcr_cassettes/api/list/retrieve_single_single.yml +9 -9
  30. data/spec/fixtures/vcr_cassettes/api/profile_extension/merge_profile_extension_records.yml +10 -10
  31. data/spec/fixtures/vcr_cassettes/api/profile_extension/retrieve_profile_extension_records.yml +10 -10
  32. data/spec/fixtures/vcr_cassettes/api/table/create_with_pk.yml +8 -8
  33. data/spec/fixtures/vcr_cassettes/api/table/delete_with_pk.yml +8 -8
  34. data/spec/fixtures/vcr_cassettes/member/present1.yml +8 -945
  35. data/spec/fixtures/vcr_cassettes/member/present2.yml +8 -8
  36. data/spec/fixtures/vcr_cassettes/member/present3.yml +8 -8
  37. data/spec/fixtures/vcr_cassettes/member/present4.yml +8 -8
  38. data/spec/fixtures/vcr_cassettes/member/present5.yml +8 -8
  39. data/spec/fixtures/vcr_cassettes/member/retrieve_profile_extension.yml +19 -19
  40. data/spec/helper_spec.rb +31 -0
  41. data/spec/member_spec.rb +12 -21
  42. data/spec/spec_helper.rb +32 -15
  43. data/spec/test_data.yml +38 -0
  44. metadata +10 -12
  45. data/spec/fixtures/vcr_cassettes/api/campaign/login.yml +0 -940
  46. data/spec/fixtures/vcr_cassettes/api/list/login.yml +0 -982
  47. data/spec/fixtures/vcr_cassettes/api/profile_extension/login.yml +0 -982
  48. data/spec/fixtures/vcr_cassettes/api/table/create.yml +0 -45
  49. data/spec/fixtures/vcr_cassettes/api/table/delete.yml +0 -45
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmRlYWRjMDA4YTliNzE3NGY2NzIzZGUyYjM3OTkyNjUyNGFkZmI1Yw==
4
+ NThlNWRiM2JmMDc1ZDJhNGM2ZjI1YWMwZjhiMGViYzM4MGI3ZGEyMw==
5
5
  data.tar.gz: !binary |-
6
- MjA4Nzc5MzFmMzVkZmNkYTlmOWZkZTZjNWMxMDM0NzhkOGQ0NDVjNw==
6
+ ZDkyMzQ2YTA3NzNlNjJhYzVkYjg1NWZmYjYyMDgzZTQ1ZWE2NzY2Nw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NTNiYzIzYjNjYWRmZDYyYWEyZWE3N2I1ODQxNmEwOTYzY2Q1M2EyNWE1NWZk
10
- ZjI2MGRmODMzZDc2OGMzZTdhM2NmMTVhOGQwZGRhN2Y5OWJkNThiNDBhYzg3
11
- Njk2NTZhOGMwMDIxZGJjNTBlY2Q2YWM1OGZhNGFlMGM3MDZiNzA=
9
+ ZjA1YzZmYjU5N2FiYzMzY2VlZjcyYTAwZWI3ZDljOTAxMDkyNjE2NzY3MmI5
10
+ ZTQ0NzAzNzYxZDIzNmVjM2RjYTA1MzhhNDMwYmNhMWMzYWY1YjQ1MzE5Yjdm
11
+ N2FhMmM0ZWEzYzExYmRkMTJmMGMxMDBmOTM0OWQwOGU2NGU0Yzc=
12
12
  data.tar.gz: !binary |-
13
- YzZmYzk1NTkwOGMyOTRmOTUyYjYxOWY1NTdkNzM1NDgyNjFlZjhkNjVkZjgy
14
- ZDkyYjU0M2E3MzYxNjc2YjE2YzAxZjUyOWVkMTk4MmUyYzA5MTBlMGU5NjVj
15
- Njg5NGYxOWEyZjc5ZjhmZGRjYTFhNGZkMDU4MDZlODE0ODJmODE=
13
+ MWFlYzk1Y2E3ZGRjYTUyNTY3NzU0ODE3NzMwZTk4ZjgyODkzYTYzZDAwODM3
14
+ ZDcxYWZmZmM4NmUyOWJlNDFhZjRkYzRmZWU4YmIzNDc3YmZmNDA5OTZjOTBj
15
+ YTc1NGQ5ZDRlOWJlY2Y0MjI2YTc5N2UxM2EwMWY0ZmRiYmVhYzA=
data/.gitignore CHANGED
@@ -20,3 +20,6 @@ lib/.DS_Store
20
20
  lib/responsys/.DS_Store
21
21
  .rvmrc
22
22
  .idea/
23
+ .ruby-version
24
+
25
+ spec/api_credentials.yml
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.1.2
5
+
6
+ gemfile:
7
+ - Gemfile
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ResponsysApi
1
+ # ResponsysApi ![Master branch build status](https://travis-ci.org/dandemeyere/responsys-api.svg?branch=master)
2
2
 
3
3
  A gem to help you communicate to the Responsys Interact SOAP API. Currently working of Responsys Interact version 6.20.
4
4
 
@@ -10,7 +10,7 @@ Have a look at our [wiki](https://github.com/dandemeyere/responsys-api/wiki) to
10
10
 
11
11
  Add this line to your application"s Gemfile:
12
12
 
13
- gem "responsys-api", "~> 0.0.6"
13
+ gem "responsys-api", "~> 0.0.8"
14
14
 
15
15
  Or install it locally with:
16
16
 
data/Rakefile CHANGED
@@ -1 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require "rake/testtask"
4
+
5
+ task :default => [:test]
6
+
7
+ task :test do
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = "spec/**/*_spec.rb"
10
+ end
11
+ Rake::Task["spec"].execute
12
+ end
@@ -6,7 +6,7 @@ module Responsys
6
6
  include Responsys::Exceptions
7
7
 
8
8
  def trigger_message(campaign, recipients)
9
- raise ParameterException, I18n.t("api.campaign.incorrect_recipients_type") unless recipients.is_a? Array
9
+ raise ParameterException, Responsys::Helper.get_message("api.campaign.incorrect_recipients_type") unless recipients.is_a? Array
10
10
  message = {
11
11
  campaign: campaign.to_api,
12
12
  recipientData: recipients.map(&:to_api)
@@ -27,12 +27,14 @@ module Responsys
27
27
  else
28
28
  @client = Savon.client(wsdl: settings[:wsdl], element_form_default: :qualified, ssl_version: ssl_version)
29
29
  end
30
-
31
- login
32
30
  end
33
31
 
34
32
  def api_method(action, message = nil, response_type = :hash)
33
+ raise Responsys::Helper.get_message("api.client.api_method.wrong_action_#{action.to_s}") if action.to_sym == :login || action.to_sym == :logout
34
+
35
35
  begin
36
+ login
37
+
36
38
  response = run_with_credentials(action, message, jsession_id, header)
37
39
 
38
40
  case response_type
@@ -43,14 +45,9 @@ module Responsys
43
45
  end
44
46
 
45
47
  rescue Exception => e
46
- error_response = Responsys::Helper.format_response_with_errors(e)
47
-
48
- if error_response[:error][:code] == "INVALID_SESSION_ID"
49
- login
50
- api_method(action, message, response_type)
51
- else
52
- error_response
53
- end
48
+ Responsys::Helper.format_response_with_errors(e)
49
+ ensure
50
+ logout
54
51
  end
55
52
  end
56
53
 
@@ -10,7 +10,7 @@ module Responsys
10
10
  if AVAILABLE_EMAIL_FORMAT.include? email_format
11
11
  @email_format_string = email_format
12
12
  else
13
- raise ParameterException, I18n.t("api.object.email_format.incorrect_email_format")
13
+ raise ParameterException, Responsys::Helper.get_message("api.object.email_format.incorrect_email_format")
14
14
  end
15
15
  end
16
16
 
@@ -10,7 +10,7 @@ module Responsys
10
10
  if FIELD_TYPES.include? field_type
11
11
  @field_type_string = field_type
12
12
  else
13
- raise ParameterException, I18n.t("api.object.field_type.incorrect_field_type")
13
+ raise ParameterException, Responsys::Helper.get_message("api.object.field_type.incorrect_field_type")
14
14
  end
15
15
  end
16
16
 
@@ -6,7 +6,7 @@ module Responsys
6
6
  attr_accessor :name, :value
7
7
 
8
8
  def initialize(name = "", value = "")
9
- raise ParameterException, I18n.t("api.object.optional_data.incorrect_optional_data_type") unless (name.is_a? String) && (value.is_a? String)
9
+ raise ParameterException, Responsys::Helper.get_message("api.object.optional_data.incorrect_optional_data_type") unless (name.is_a? String) && (value.is_a? String)
10
10
  @name = name
11
11
  @value = value
12
12
  end
@@ -10,7 +10,7 @@ module Responsys
10
10
  if AVAILABLE_QUERY_COLUMN.include? query_column
11
11
  @query_column_string = query_column
12
12
  else
13
- raise ParameterException, I18n.t("api.object.query_column.incorrect_query_column")
13
+ raise ParameterException, Responsys::Helper.get_message("api.object.query_column.incorrect_query_column")
14
14
  end
15
15
  end
16
16
 
@@ -6,7 +6,7 @@ module Responsys
6
6
  attr_accessor :field_values
7
7
 
8
8
  def initialize(field_values)
9
- raise ParameterException, I18n.t("api.object.record.incorrect_field_values_type") unless field_values.is_a? Array
9
+ raise ParameterException, Responsys::Helper.get_message("api.object.record.incorrect_field_values_type") unless field_values.is_a? Array
10
10
  @field_values = field_values
11
11
  end
12
12
 
@@ -7,7 +7,7 @@ module Responsys
7
7
  attr_accessor :field_names, :records
8
8
 
9
9
  def initialize(data)
10
- raise ParameterException, I18n.t("api.object.record_data.incorrect_record_data_type") unless data.is_a? Array
10
+ raise ParameterException, Responsys::Helper.get_message("api.object.record_data.incorrect_record_data_type") unless data.is_a? Array
11
11
 
12
12
  self.field_names = data.map { |record| record.keys }.flatten.uniq
13
13
 
@@ -2,6 +2,8 @@ module Responsys
2
2
  module Api
3
3
  module Session
4
4
  def login
5
+ logout if logged_in?
6
+
5
7
  response = run("login", credentials)
6
8
  establish_session_id(response)
7
9
  establish_jsession_id(response)
@@ -9,7 +11,14 @@ module Responsys
9
11
  end
10
12
 
11
13
  def logout
12
- api_method(:logout)
14
+ return unless logged_in?
15
+
16
+ run_with_credentials(:logout, nil, jsession_id, header)
17
+ destroy_session_objects
18
+ end
19
+
20
+ def logged_in?
21
+ !(session_id.nil? || jsession_id.nil? || header.nil?)
13
22
  end
14
23
 
15
24
  private
@@ -25,6 +34,12 @@ module Responsys
25
34
  def set_session_credentials
26
35
  @header = { SessionHeader: { sessionId: session_id } }
27
36
  end
37
+
38
+ def destroy_session_objects
39
+ @session_id = nil
40
+ @jsession_id = nil
41
+ @header = nil
42
+ end
28
43
  end
29
44
  end
30
45
  end
@@ -77,7 +77,15 @@ module Responsys
77
77
  end
78
78
 
79
79
  def self.format_response_with_message(i18n_key)
80
- { status: "failure", error: { http_status_code: "", code: i18n_key.split('.')[-1], message: I18n.t(i18n_key) } }
80
+ { status: "failure", error: { http_status_code: "", code: i18n_key.split('.')[-1], message: get_message(i18n_key) } }
81
+ end
82
+
83
+ def self.get_message(key)
84
+ begin
85
+ I18n.t(key, scope: :responsys_api, locale: I18n.locale, raise: true)
86
+ rescue I18n::MissingTranslationData
87
+ I18n.t(key, scope: :responsys_api, locale: :en)
88
+ end
81
89
  end
82
90
  end
83
91
  end
@@ -1,20 +1,25 @@
1
1
  en:
2
- api:
3
- object:
4
- field_type:
5
- incorrect_field_type: The field type string you provided is incorrect
6
- query_column:
7
- incorrect_query_column: The query column you provided is incorrect
8
- record_data:
9
- incorrect_record_data_type: The data you provided is not an array
10
- optional_data:
11
- incorrect_optional_data_type: The name and value need to be Strings
12
- email_format:
13
- incorrect_email_format: The email format is not supported
14
- record:
15
- incorrect_field_values_type: The field_values must be an array
16
- campaign:
17
- incorrect_recipients_type: Recipients parameter must be an array
18
- member:
19
- riid_missing: Variable riid is not provided to the member
20
- record_not_found: The member has not been found in the list
2
+ responsys_api:
3
+ api:
4
+ object:
5
+ field_type:
6
+ incorrect_field_type: The field type string you provided is incorrect
7
+ query_column:
8
+ incorrect_query_column: The query column you provided is incorrect
9
+ record_data:
10
+ incorrect_record_data_type: The data you provided is not an array
11
+ optional_data:
12
+ incorrect_optional_data_type: The name and value need to be Strings
13
+ email_format:
14
+ incorrect_email_format: The email format is not supported
15
+ record:
16
+ incorrect_field_values_type: The field_values must be an array
17
+ client:
18
+ api_method:
19
+ wrong_action_login: Please use the dedicated login method
20
+ wrong_action_logout: Please use the dedicated logout method
21
+ campaign:
22
+ incorrect_recipients_type: Recipients parameter must be an array
23
+ member:
24
+ riid_missing: Variable riid is not provided to the member
25
+ record_not_found: The member has not been found in the list
@@ -0,0 +1,21 @@
1
+ fr:
2
+ responsys_api:
3
+ api:
4
+ object:
5
+ field_type:
6
+ incorrect_field_type: Le type fourni à l'objet FieldType est incorrect
7
+ query_column:
8
+ incorrect_query_column: La colonne de recherche est incorrecte
9
+ record_data:
10
+ incorrect_record_data_type: La donnée fournie n'est pas de type Array
11
+ optional_data:
12
+ incorrect_optional_data_type: Le nom et la valeur doivent être de type String
13
+ email_format:
14
+ incorrect_email_format: Le format de l'email est incorrect
15
+ record:
16
+ incorrect_field_values_type: L'objet fournissant les valeurs doit être de type Array
17
+ campaign:
18
+ incorrect_recipients_type: La liste des destinataires doit être de type Array
19
+ member:
20
+ riid_missing: Le riid n'est pas fournie à l'objet Member
21
+ record_not_found: L'enregistrement n'a pas été trouvé dans la liste
@@ -1,8 +1,6 @@
1
1
  require "i18n"
2
2
 
3
- I18n.load_path << File.expand_path("../responsys/i18n/en.yml", __FILE__)
4
- I18n.locale = :en
5
- I18n.enforce_available_locales = false
3
+ I18n.load_path.concat Dir.glob( File.dirname(__FILE__) + "/responsys/i18n/*.yml" )
6
4
 
7
5
  require "responsys/exceptions/all"
8
6
  require "responsys/helper"
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "responsys-api"
7
- spec.version = "0.0.8"
7
+ spec.version = "0.0.9"
8
8
  spec.authors = ["Dan DeMeyere", "Florian Lorrain", "Morgan Griggs", "Mike Rocco"]
9
9
  spec.email = ["dan@thredup.com", "florian.lorrain@thredup.com", "morgan@thredup.com", "michael.rocco@thredup.com"]
10
10
  spec.description = "A gem to integrate with the Responsys SOAP API"
@@ -5,9 +5,7 @@ describe Responsys::Api::Campaign do
5
5
 
6
6
  context "Trigger Message" do
7
7
  before(:all) do
8
- VCR.use_cassette("api/campaign/login") do
9
- @client = Responsys::Api::Client.instance
10
- end
8
+ @client = Responsys::Api::Client.instance
11
9
  end
12
10
 
13
11
  before(:each) do
@@ -17,10 +15,8 @@ describe Responsys::Api::Campaign do
17
15
  end
18
16
 
19
17
  it "should pass api_method a message Hash" do
20
- VCR.use_cassette("api/campaign/login") do
21
- expect(@client).to receive(:api_method).with(anything, be_a_kind_of(Hash))
22
- @client.trigger_message(@campaign, [@recipientData])
23
- end
18
+ expect(@client).to receive(:api_method).with(anything, be_a_kind_of(Hash))
19
+ @client.trigger_message(@campaign, [@recipientData])
24
20
  end
25
21
  end
26
22
 
@@ -4,43 +4,12 @@ require "singleton"
4
4
 
5
5
  describe Responsys::Api::Client do
6
6
 
7
- context "expired session" do
8
- before(:example) do
9
- allow_any_instance_of(Responsys::Api::Client).to receive(:login).and_return(nil)
10
-
11
- Responsys::Api::Client.instance.instance_variable_set(:@session_id, "fake_session_id")
12
- Responsys::Api::Client.instance.instance_variable_set(:@jsession_id, HTTPI::Cookie.new("jsessionid=fakejsessionid; Path=/; HttpOnly"))
13
- Responsys::Api::Client.instance.instance_variable_set(:@header, { SessionHeader: { sessionId: "fake_session_id" } })
14
- end
15
-
16
- it "should ask for a new session" do
17
- VCR.use_cassette("api/client/expired_session") do
18
- expect_any_instance_of(Responsys::Api::Client).to receive(:login).exactly(1).times.and_call_original
19
- result = Responsys::Api::Client.instance.api_method(:list_folders)
20
-
21
- expect(result[:status]).to eq("ok")
22
- end
23
- end
24
-
25
- it "should rerun the request with a new session id" do
26
- VCR.use_cassette("api/client/expired_session") do
27
- expect_any_instance_of(Responsys::Api::Client).to receive(:login).exactly(1).times.and_call_original
28
-
29
- expect(Responsys::Api::Client.instance.header[:SessionHeader][:sessionId]).to eq("fake_session_id")
30
-
31
- Responsys::Api::Client.instance.api_method(:list_folders)
32
-
33
- expect(Responsys::Api::Client.instance.header[:SessionHeader][:sessionId]).to eq("5GXdGHHKOLqsf4ukCpwQYz3B0b")
34
- end
35
- end
36
-
37
- end
38
-
39
7
  context "Authentication" do
8
+ subject { Responsys::Api::Client.instance }
40
9
  let(:savon_client) { double("savon client") }
41
10
 
42
11
  before(:context) do
43
- @credentials = { username: "your_responsys_username", password: "your_responsys_password" }
12
+ @credentials = { username: CREDENTIALS["username"], password: CREDENTIALS["password"] }
44
13
  end
45
14
 
46
15
  after(:context) do
@@ -52,7 +21,7 @@ describe Responsys::Api::Client do
52
21
 
53
22
  responsys = Responsys::Api::Client.instance
54
23
 
55
- expect(responsys.credentials).to eq({ username: "your_responsys_username", password: "your_responsys_password" })
24
+ expect(responsys.credentials).to eq({ username: CREDENTIALS["username"], password: CREDENTIALS["password"] })
56
25
  end
57
26
 
58
27
  context "login" do
@@ -71,7 +40,7 @@ describe Responsys::Api::Client do
71
40
  allow(response).to receive(:body).and_return(body)
72
41
  allow(response).to receive(:http).and_return(double("cookies", cookies: cookies))
73
42
 
74
- allow(Savon).to receive(:client).with({ wsdl: "https://wsxxxx.responsys.net/webservices/wsdl/ResponsysWS_Level1.wsdl", element_form_default: :qualified, ssl_version: :TLSv1}).and_return(savon_client) #Avoid the verification of the wsdl
43
+ allow(Savon).to receive(:client).with({ wsdl: CREDENTIALS["wsdl"], element_form_default: :qualified, ssl_version: :TLSv1}).and_return(savon_client) #Avoid the verification of the wsdl
75
44
  allow_any_instance_of(Responsys::Api::Client).to receive(:run).with("login", @credentials).and_return(response) #Verification of credentials
76
45
  allow(savon_client).to receive(:call).with(:login, @credentials ).and_return(response) #Actual login call
77
46
 
@@ -79,28 +48,29 @@ describe Responsys::Api::Client do
79
48
  end
80
49
 
81
50
  it "should set the session ids" do
82
- instance = Responsys::Api::Client.instance #Get it
51
+ subject.login
52
+
53
+ expect(subject.header).to eq({ SessionHeader: { sessionId: "fake_session_id" } }) #Test the ids are right
54
+ expect(subject.jsession_id).to eq("fake_jsession_id")
55
+ end
83
56
 
84
- expect(instance.header).to eq({ SessionHeader: { sessionId: "fake_session_id" } }) #Test the ids are right
85
- expect(instance.jsession_id).to eq("fake_jsession_id")
57
+ it "should refuse the access to api_method for login" do
58
+ expect{ subject.api_method(:login) }.to raise_error("Please use the dedicated login method")
86
59
  end
87
60
  end
88
61
 
89
62
  context "logout" do
90
- before(:example) do
91
- allow(Savon).to receive(:client).with({ wsdl: "https://wsxxxx.responsys.net/webservices/wsdl/ResponsysWS_Level1.wsdl", element_form_default: :qualified, ssl_version: :TLSv1}).and_return(savon_client) #Avoid the verification of the wsdl
92
- allow_any_instance_of(Responsys::Api::Client).to receive(:login).and_return(nil) #Avoid credentials checking
93
-
94
- Singleton.__init__(Responsys::Api::Client)
95
- end
63
+ subject { Responsys::Api::Client.instance }
96
64
 
97
65
  it "should logout" do
98
- instance = Responsys::Api::Client.instance #Get it
66
+ allow(subject).to receive(:logged_in?).and_return(true)
67
+ expect(subject).to receive(:run_with_credentials).with(:logout, anything, anything, anything) #Check the call is actually being done
99
68
 
100
- allow(Responsys::Helper).to receive(:format_response_hash).with(any_args) #We dont want to parse the response
101
- expect(savon_client).to receive(:call).with(:logout, anything) #Check the call is actually being done
69
+ subject.logout
70
+ end
102
71
 
103
- instance.logout
72
+ it "should refuse the access to api_method for logout" do
73
+ expect{ subject.api_method(:logout) }.to raise_error("Please use the dedicated logout method")
104
74
  end
105
75
  end
106
76
  end