survey-gizmo-ruby 1.0.5 → 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.
@@ -0,0 +1,82 @@
1
+ # This class normalizes the response returned by Survey Gizmo
2
+ class RestResponse
3
+ attr_accessor :raw_response
4
+ attr_accessor :parsed_response
5
+
6
+ def initialize(rest_response)
7
+ @raw_response = rest_response
8
+ @parsed_response = rest_response.parsed_response
9
+ return unless data
10
+
11
+ # Handle really crappy [] notation in SG API, so far just in SurveyResponse
12
+ (data.is_a?(Array) ? data : [data]).each do |datum|
13
+ datum.keys.grep(/^\[/).each do |key|
14
+ next if datum[key].nil? || datum[key].length == 0
15
+
16
+ parent = find_attribute_parent(key)
17
+ datum[parent] ||= {}
18
+
19
+ case key.downcase
20
+ when /(url|variable.*standard)/
21
+ datum[parent][cleanup_attribute_name(key).to_sym] = datum[key]
22
+ when /variable.*shown/
23
+ datum[parent][cleanup_attribute_name(key).to_i] = datum[key].include?('1')
24
+ when /variable/
25
+ datum[parent][cleanup_attribute_name(key).to_i] = datum[key].to_i
26
+ when /question/
27
+ datum[parent][key] = datum[key]
28
+ end
29
+
30
+ datum.delete(key)
31
+ end
32
+ end
33
+ end
34
+
35
+ def ok?
36
+ if ENV['GIZMO_DEBUG']
37
+ ap 'SG Response: '
38
+ ap @parsed_response
39
+ end
40
+
41
+ if @parsed_response['result_ok'] && @parsed_response['result_ok'].to_s.downcase == 'false' && @parsed_response['message'] && @parsed_response['code'] && @parsed_response['message'] =~ /service/i
42
+ raise Exception, "#{@parsed_response['message']}: #{@parsed_response['code']}"
43
+ end
44
+ @parsed_response['result_ok'] && @parsed_response['result_ok'].to_s.downcase == 'true'
45
+ end
46
+
47
+ # The parsed JSON data of the response
48
+ def data
49
+ @_data ||= @parsed_response['data'] #|| {'id' => @parsed_response['id']}
50
+ end
51
+
52
+ # The error message if there is one
53
+ def message
54
+ @_message ||= @parsed_response['message']
55
+ end
56
+
57
+
58
+ private
59
+
60
+ def cleanup_attribute_name(attr)
61
+ attr.downcase.gsub(/[^[:alnum:]]+/, '_')
62
+ .gsub(/(url|variable|standard|shown)/, '')
63
+ .gsub(/_+/, '_')
64
+ .gsub(/^_/, '')
65
+ .gsub(/_$/, '')
66
+ end
67
+
68
+ def find_attribute_parent(attr)
69
+ case attr.downcase
70
+ when /url/
71
+ 'url'
72
+ when /variable.*standard/
73
+ 'meta'
74
+ when /variable.*shown/
75
+ 'shown'
76
+ when /variable/
77
+ 'variable'
78
+ when /question/
79
+ 'answers'
80
+ end
81
+ end
82
+ end
@@ -1,23 +1,24 @@
1
- require "active_support/core_ext/string"
2
- require "active_support/core_ext/module"
3
- require "active_support/core_ext/hash"
4
- require "active_support/core_ext/object/blank"
5
- require "active_support/concern"
6
- require "virtus"
7
- require "httparty"
8
- require "digest/md5"
9
-
10
- require "survey_gizmo/resource"
11
- require "survey_gizmo/collection"
12
-
13
- require "survey_gizmo/api/survey"
14
- require "survey_gizmo/api/survey_campaign"
15
- require "survey_gizmo/api/question"
16
- require "survey_gizmo/api/option"
17
- require "survey_gizmo/api/page"
18
- require "survey_gizmo/api/contact"
19
- require "survey_gizmo/api/response"
20
- require "survey_gizmo/api/email_message"
1
+ require 'active_support/core_ext/string'
2
+ require 'active_support/core_ext/module'
3
+ require 'active_support/core_ext/hash'
4
+ require 'active_support/core_ext/object/blank'
5
+ require 'active_support/concern'
6
+ require 'awesome_print'
7
+ require 'virtus'
8
+ require 'httparty'
9
+ require 'digest/md5'
10
+
11
+ require 'survey_gizmo/resource'
12
+ require 'survey_gizmo/rest_response'
13
+
14
+ require 'survey_gizmo/api/survey'
15
+ require 'survey_gizmo/api/survey_campaign'
16
+ require 'survey_gizmo/api/question'
17
+ require 'survey_gizmo/api/option'
18
+ require 'survey_gizmo/api/page'
19
+ require 'survey_gizmo/api/contact'
20
+ require 'survey_gizmo/api/response'
21
+ require 'survey_gizmo/api/email_message'
21
22
 
22
23
  module SurveyGizmo
23
24
  include HTTParty
@@ -42,7 +43,11 @@ module SurveyGizmo
42
43
  # The account password
43
44
  def self.setup(opts = {})
44
45
  self.options = opts
45
- default_params({ "user:md5" => "#{opts[:user]}:#{Digest::MD5.hexdigest(opts[:password])}" })
46
+ default_params({ 'user:md5' => "#{opts[:user]}:#{Digest::MD5.hexdigest(opts[:password])}" })
46
47
  end
47
48
 
48
- end
49
+ def self.reset
50
+ @@options = {}
51
+ default_params({})
52
+ end
53
+ end
@@ -1,56 +1,61 @@
1
- require "spec_helper"
2
- describe "Survey Gizmo Resource" do
1
+ require 'spec_helper'
2
+ describe 'Survey Gizmo Resource' do
3
3
 
4
4
  describe SurveyGizmo::Resource do
5
5
  before(:each) do
6
- SurveyGizmo.setup(:user => 'test@test.com', :password => 'password')
6
+ SurveyGizmo.setup(user: 'test@test.com', password: 'password')
7
7
  end
8
8
 
9
- let(:described_class) { SurveyGizmoSpec::ResourceTest }
10
-
11
- let(:create_attributes){ {:title => 'Spec', :test_id => 5} }
12
- let(:get_attributes) { create_attributes.merge(:id => 1) }
13
- let(:update_attributes){ {:title => 'Updated'} }
14
- let(:first_params){ {:id => 1, :test_id => 5} }
9
+ let(:described_class) { SurveyGizmoSpec::ResourceTest }
10
+ let(:create_attributes) { {title: 'Spec', test_id: 5} }
11
+ let(:update_attributes) { {title: 'Updated'} }
12
+ let(:first_params) { {id: 1, test_id: 5} }
13
+ let(:get_attributes) { create_attributes.merge(id: 1) }
15
14
  let(:uri_paths){
16
15
  {
17
- :get => '/test/1',
18
- :create => '/test/5/resource',
19
- :update => '/test/5/resource/1',
20
- :delete => '/test/5/resource/1'
16
+ get: '/test/1',
17
+ create: '/test/5/resource',
18
+ update: '/test/5/resource/1',
19
+ delete: '/test/5/resource/1'
21
20
  }
22
21
  }
23
22
 
24
- it "#new?" do
25
- described_class.new.should be_new
26
- end
27
-
28
-
29
23
  it '#reload' do
30
24
  stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
31
25
  obj = described_class.new(get_attributes.merge(update_attributes))
32
- obj.attributes.reject{|k,v| v.blank? }.should == get_attributes.merge(update_attributes)
26
+ obj.attributes.reject {|k,v| v.blank? }.should == get_attributes.merge(update_attributes)
33
27
  obj.reload
34
- obj.attributes.reject{|k,v| v.blank? }.should == get_attributes
28
+ obj.attributes.reject {|k,v| v.blank? }.should == get_attributes
35
29
  end
36
30
 
37
- it '#valid?'
38
-
39
- it "should raise an error if params are missing" do
31
+ it 'should raise an error if params are missing' do
40
32
  lambda {
41
- SurveyGizmoSpec::ResourceTest.destroy(:test_id => 5)
42
- }.should raise_error(SurveyGizmo::URLError, 'Missing parameters in request: `:id`')
33
+ SurveyGizmoSpec::ResourceTest.destroy(test_id: 5)
34
+ }.should raise_error(SurveyGizmo::URLError, 'Missing RESTful parameters in request: `:id`')
43
35
  end
44
36
 
45
37
  it_should_behave_like 'an API object'
46
38
  it_should_behave_like 'an object with errors'
39
+
40
+ context '#convert_filters_into_query_string' do
41
+ let(:page) { 2 }
42
+ let(:filters) { {page: page, filters: [{field: 'istestdata', operator: '<>', value: 1}] }}
43
+
44
+ it 'should generate the correct page request' do
45
+ expect(SurveyGizmoSpec::ResourceTest.convert_filters_into_query_string(page: page)).to eq("?page=#{page}")
46
+ end
47
+
48
+ it 'should generate the correct filter fragment' do
49
+ expect(SurveyGizmoSpec::ResourceTest.convert_filters_into_query_string(filters)).to eq("?filter%5Bfield%5D%5B0%5D=istestdata&filter%5Boperator%5D%5B0%5D=%3C%3E&filter%5Bvalue%5D%5B0%5D=1&page=#{page}")
50
+ end
51
+ end
47
52
  end
48
53
 
49
54
  describe SurveyGizmo::API::Survey do
50
- let(:create_attributes){ {:title => 'Spec', :type => 'survey', :status => 'In Design'} }
51
- let(:get_attributes) { create_attributes.merge(:id => 1234) }
52
- let(:update_attributes){ {:title => 'Updated'} }
53
- let(:first_params){ {:id => 1234} }
55
+ let(:create_attributes) { { title: 'Spec', type: 'survey', status: 'In Design' } }
56
+ let(:get_attributes) { create_attributes.merge(first_params) }
57
+ let(:update_attributes) { { title: 'Updated'} }
58
+ let(:first_params) { { id: 1234} }
54
59
  let(:uri_paths){
55
60
  h = { :create => '/survey' }
56
61
  h.default = '/survey/1234'
@@ -59,16 +64,20 @@ describe "Survey Gizmo Resource" do
59
64
 
60
65
  it_should_behave_like 'an API object'
61
66
  it_should_behave_like 'an object with errors'
67
+
68
+ it 'should parse the number of completed records correctly' do
69
+ survey = described_class.new('statistics' => [['Partial', 2], ['Disqualified', 28], ['Complete', 15]])
70
+ expect(survey.number_of_completed_responses).to eq(15)
71
+ end
62
72
  end
63
73
 
64
74
  describe SurveyGizmo::API::Question do
65
- let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Spec Question', :type => 'radio', :properties => {"required" => true, "option_sort" => false} } }
66
- let(:get_attributes) {
67
- create_attributes.merge(:id => 1)
68
- }
69
- let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :title => 'Updated'} }
70
- let(:first_params){ {:id => 1, :survey_id => 1234, :page_id => 1} }
71
- let(:uri_paths){
75
+ let(:base_params) { {survey_id: 1234, page_id: 1} }
76
+ let(:create_attributes) { base_params.merge(title: 'Spec Question', type: 'radio', properties: {'required' => true, 'option_sort' => false}) }
77
+ let(:update_attributes) { base_params.merge(title: 'Updated') }
78
+ let(:first_params) { base_params.merge(id: 1) }
79
+ let(:get_attributes) { create_attributes.merge(id: 1) }
80
+ let(:uri_paths) {
72
81
  { :get => '/survey/1234/surveyquestion/1',
73
82
  :create => '/survey/1234/surveypage/1/surveyquestion',
74
83
  :update => '/survey/1234/surveypage/1/surveyquestion/1',
@@ -79,25 +88,44 @@ describe "Survey Gizmo Resource" do
79
88
  it_should_behave_like 'an API object'
80
89
  it_should_behave_like 'an object with errors'
81
90
 
82
- it "should handle the title hash returned from the API" do
83
- @question = described_class.new('title' => {'English' => 'Some title'})
84
- @question.title.should == 'Some title'
91
+ it 'should handle the title hash returned from the API' do
92
+ expect(described_class.new('title' => {'English' => 'Some title'}).title).to eq('Some title')
93
+ end
94
+
95
+ it 'should handle the _subtype key' do
96
+ described_class.new(:_subtype => 'radio').type.should == 'radio'
85
97
  end
86
98
 
87
- it "should handle the _subtype key" do
88
- @question = described_class.new(:_subtype => 'radio')
89
- @question.type.should == 'radio'
99
+ it 'should have no subquestions' do
100
+ expect(described_class.new().sub_questions).to eq([])
101
+ end
102
+
103
+ it 'should find the survey' do
104
+ stub_request(:get, /#{@base}\/survey\/1234/).to_return(json_response(true, get_attributes))
105
+ described_class.new(base_params).survey
106
+ a_request(:get, /#{@base}\/survey\/1234/).should have_been_made
107
+ end
108
+
109
+ context 'with subquestions' do
110
+ let(:parent_id) { 33 }
111
+ let(:question_with_subquestions) { described_class.new(id: parent_id, survey_id: 1234, sub_question_skus: [1, 2])}
112
+ it 'should have 2 subquestions and they should have the right parent question' do
113
+ stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
114
+ expect(question_with_subquestions.sub_questions.size).to eq(2)
115
+
116
+ question_with_subquestions.sub_questions.first.parent_question
117
+ a_request(:get, /#{@base}\/survey\/1234\/surveyquestion\/#{parent_id}/).should have_been_made
118
+ end
90
119
  end
91
120
  end
92
121
 
93
122
  describe SurveyGizmo::API::Option do
94
- let(:create_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Spec Question', :value => 'Spec Answer'} }
95
- let(:get_attributes) {
96
- create_attributes.merge(:id => 1)
97
- }
98
- let(:update_attributes){ {:survey_id => 1234, :page_id => 1, :question_id => 1, :title => 'Updated'} }
99
- let(:first_params){ {:id => 1, :survey_id => 1234, :page_id => 1, :question_id => 1} }
100
- let(:uri_paths){
123
+ let(:survey_and_page) { {survey_id: 1234, page_id: 1} }
124
+ let(:create_attributes) { survey_and_page.merge(question_id: 1, title: 'Spec Question', value: 'Spec Answer') }
125
+ let(:update_attributes) { survey_and_page.merge(question_id: 1, title: 'Updated') }
126
+ let(:first_params) { survey_and_page.merge(id: 1, question_id: 1) }
127
+ let(:get_attributes) { create_attributes.merge(id: 1) }
128
+ let(:uri_paths) {
101
129
  h = { :create => '/survey/1234/surveypage/1/surveyquestion/1/surveyoption' }
102
130
  h.default = '/survey/1234/surveypage/1/surveyquestion/1/surveyoption/1'
103
131
  h
@@ -108,12 +136,10 @@ describe "Survey Gizmo Resource" do
108
136
  end
109
137
 
110
138
  describe SurveyGizmo::API::Page do
111
- let(:create_attributes){ {:survey_id => 1234, :title => {'English' => 'Spec Page'}} }
112
- let(:get_attributes) {
113
- create_attributes.merge(:id => 1)
114
- }
115
- let(:update_attributes){ {:survey_id => 1234, :title => 'Updated'} }
116
- let(:first_params){ {:id => 1, :survey_id => 1234 } }
139
+ let(:create_attributes) { {:survey_id => 1234, :title => {'English' => 'Spec Page'}} }
140
+ let(:get_attributes) { create_attributes.merge(:id => 1) }
141
+ let(:update_attributes) { {:survey_id => 1234, :title => 'Updated'} }
142
+ let(:first_params) { {:id => 1, :survey_id => 1234 } }
117
143
  let(:uri_paths){
118
144
  h = { :create => '/survey/1234/surveypage' }
119
145
  h.default = '/survey/1234/surveypage/1'
@@ -5,13 +5,16 @@ module SurveyGizmoSpec
5
5
  end
6
6
 
7
7
  def request_params(opts = {})
8
- {"user:pass" => 'test@test.com:password'}.merge(opts)
8
+ {'user:pass' => 'test@test.com:password'}.merge(opts)
9
9
  end
10
10
 
11
11
  def json_response(result, data)
12
- body = {:result_ok => result}
13
- result ? body.merge!(:data => data) : body.merge!(:message => data)
14
- {:headers => {'Content-Type' => 'application/json'}, :body => body.to_json}
12
+ body = {result_ok: result}
13
+ result ? body.merge!(data: data) : body.merge!(message: data)
14
+ {
15
+ headers: {'Content-Type' => 'application/json'},
16
+ body: body.to_json
17
+ }
15
18
  end
16
19
  end
17
20
  end
@@ -1,126 +1,81 @@
1
1
  shared_examples_for 'an API object' do
2
- before(:each) do
3
- SurveyGizmo.setup(:user => 'test@test.com', :password => 'password')
2
+ before(:all) do
3
+ SurveyGizmo.setup(user: 'test@test.com', password: 'password')
4
4
  end
5
-
5
+
6
6
  it "should be descendant of SurveyGizmo::Resource" do
7
7
  SurveyGizmo::Resource.descendants.should include(described_class)
8
8
  end
9
-
10
-
9
+
11
10
  context "#create" do
12
11
  it "should make a request" do
13
12
  stub_api_call(:put)
14
13
  described_class.create(create_attributes)
15
14
  a_request(:put, /#{@base}#{uri_paths[:create]}/).should have_been_made
16
15
  end
17
-
16
+
18
17
  it "should return a new instance" do
19
18
  stub_api_call(:put)
20
19
  obj = described_class.create(create_attributes)
21
20
  obj.should be_instance_of(described_class)
22
21
  end
23
-
22
+
24
23
  it "should set the attributes" do
25
24
  stub_request(:put, /#{@base}/).to_return(json_response(true, create_attributes))
26
25
  obj = described_class.create(create_attributes)
27
26
  obj.attributes.reject{|k,v| v.blank? }.should == create_attributes
28
27
  end
29
28
  end
30
-
29
+
31
30
  context "#get" do
32
31
  it "should make a request" do
33
32
  stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
34
33
  described_class.first(first_params)
35
34
  a_request(:get, /#{@base}#{uri_paths[:get]}/).should have_been_made
36
35
  end
37
-
36
+
38
37
  it "should set the attributes" do
39
38
  stub_request(:get, /#{@base}/).to_return(json_response(true, get_attributes))
40
39
  obj = described_class.first(first_params)
41
40
  obj.attributes.reject{|k,v| v.blank? }.should == get_attributes
42
41
  end
43
-
42
+
44
43
  it "should return false if the request fails" do
45
44
  stub_request(:get, /#{@base}/).to_return(json_response(false, "something is wrong"))
46
45
  described_class.first(first_params).should == nil
47
46
  end
48
47
  end
49
-
50
- context "instance#update" do
51
- before(:each) do
52
- @obj = described_class.new(get_attributes)
53
- @obj.__send__(:clean!)
54
- end
55
-
56
- it "should make a request" do
57
- stub_api_call(:post)
58
- @obj.update
59
- a_request(:post, /#{@base}#{uri_paths[:update]}/).should have_been_made
60
- end
61
-
62
- it 'should change object state to saved' do
63
- stub_api_call(:post)
64
- @obj.update(update_attributes)
65
- @obj.should be_saved
66
- end
67
-
68
- it "should not be marked saved if the request fails" do
69
- stub_api_call(:post, false)
70
- @obj.update
71
- @obj.should_not be_saved
72
- end
73
-
74
- xit "cannot be updated if new" do
75
- @obj.instance_variable_set('@_state', nil)
76
- @obj.update(update_attributes).should be_false
77
- end
78
-
79
- end
80
-
48
+
81
49
  context "instance#destroy" do
82
50
  before(:each) do
83
51
  @obj = described_class.new(get_attributes)
84
- @obj.__send__(:clean!)
85
52
  end
86
-
53
+
87
54
  it "should make a request" do
88
55
  stub_api_call(:delete)
89
56
  @obj.destroy
90
57
  a_request(:delete, /#{@base}#{uri_paths[:delete]}/).should have_been_made
91
58
  end
92
-
93
- it 'should change object state to destroyed' do
94
- stub_api_call(:delete)
95
- @obj.destroy
96
- @obj.should be_destroyed
97
- end
98
-
99
- it "should not be marked destroyed if the request fails" do
100
- stub_api_call(:delete, false)
101
- @obj.destroy
102
- @obj.should_not be_destroyed
103
- end
104
-
59
+
105
60
  it "cannot be destroyed if new" do
106
- @obj.instance_variable_set('@_state', nil)
61
+ @obj.id = nil
107
62
  @obj.destroy.should be_false
108
63
  end
109
64
  end
110
-
65
+
111
66
  context '#destroy', :focused => true do
112
67
  it "should make a request" do
113
68
  stub_api_call(:delete)
114
69
  described_class.destroy(first_params)
115
70
  a_request(:delete, /#{@base}#{uri_paths[:delete]}/).should have_been_made
116
71
  end
117
-
72
+
118
73
  it "should return result" do
119
74
  stub_api_call(:delete)
120
75
  described_class.destroy(first_params).should be_true
121
76
  end
122
77
  end
123
-
78
+
124
79
  context 'instance#save' do
125
80
  it "should call create on a new resource" do
126
81
  stub_api_call(:put)
@@ -128,16 +83,15 @@ shared_examples_for 'an API object' do
128
83
  obj.save
129
84
  a_request(:put, /#{@base}#{uri_paths[:create]}/).should have_been_made
130
85
  end
131
-
86
+
132
87
  it "should call update on a created resource" do
133
88
  obj = described_class.new(get_attributes)
134
- obj.__send__(:clean!)
135
89
  stub_api_call(:post)
136
90
  obj.save
137
91
  a_request(:post, /#{@base}#{uri_paths[:update]}/).should have_been_made
138
92
  end
139
93
  end
140
-
94
+
141
95
  context '#all' do
142
96
  before(:all) do
143
97
  @array = [
@@ -146,30 +100,30 @@ shared_examples_for 'an API object' do
146
100
  {:id => 3, :title => 'resource 3'}
147
101
  ]
148
102
  end
149
-
103
+
150
104
  it "should make a get request" do
151
105
  stub_request(:get, /#{@base}/).to_return(json_response(true, []))
152
106
  described_class.all(get_attributes)
153
107
  a_request(:get, /#{@base}#{uri_paths[:create]}/).should have_been_made
154
108
  end
155
-
109
+
156
110
  it "should create a collection using the class" do
157
111
  stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
158
112
  collection = described_class.all(get_attributes)
159
- collection.should be_instance_of(SurveyGizmo::Collection)
160
- end
161
-
113
+ collection.should be_instance_of(Array)
114
+ end
115
+
162
116
  it "should return instances of the class" do
163
117
  stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
164
118
  collection = described_class.all(get_attributes)
165
119
  collection.first.should be_instance_of(described_class)
166
120
  end
167
-
121
+
168
122
  it "should include all elements" do
169
123
  stub_request(:get, /#{@base}/).to_return(json_response(true, @array))
170
124
  collection = described_class.all(get_attributes)
171
125
  collection.length.should == 3
172
126
  end
173
127
  end
174
-
128
+
175
129
  end