solidus_reviews 1.0.0 → 1.1.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.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +322 -0
  3. data/.travis.yml +27 -14
  4. data/Gemfile +23 -8
  5. data/LICENSE.md +2 -2
  6. data/README.md +9 -11
  7. data/Rakefile +2 -0
  8. data/app/controllers/spree/admin/feedback_reviews_controller.rb +3 -1
  9. data/app/controllers/spree/admin/review_settings_controller.rb +3 -1
  10. data/app/controllers/spree/admin/reviews_controller.rb +9 -6
  11. data/app/controllers/spree/feedback_reviews_controller.rb +25 -19
  12. data/app/controllers/spree/products_controller_decorator.rb +2 -0
  13. data/app/controllers/spree/reviews_controller.rb +11 -7
  14. data/app/helpers/spree/api/api_helpers_decorator.rb +12 -0
  15. data/app/helpers/spree/reviews_helper.rb +15 -5
  16. data/app/models/spree/feedback_review.rb +5 -4
  17. data/app/models/spree/product_decorator.rb +5 -4
  18. data/app/models/spree/review.rb +28 -10
  19. data/app/models/spree/reviews_ability.rb +17 -3
  20. data/app/models/spree/reviews_configuration.rb +16 -8
  21. data/app/models/spree/user_decorator.rb +3 -0
  22. data/app/overrides/add_reviews_after_product_properties.rb +7 -5
  23. data/app/overrides/add_reviews_tab_to_admin.rb +12 -4
  24. data/app/overrides/add_reviews_to_admin_configuration_sidebar.rb +13 -5
  25. data/app/views/spree/admin/feedback_reviews/index.html.erb +9 -9
  26. data/app/views/spree/admin/review_settings/edit.html.erb +64 -35
  27. data/app/views/spree/admin/reviews/_form.html.erb +26 -5
  28. data/app/views/spree/admin/reviews/edit.html.erb +2 -2
  29. data/app/views/spree/admin/reviews/index.html.erb +100 -88
  30. data/app/views/spree/api/reviews/_review.json.jbuilder +8 -0
  31. data/app/views/spree/api/reviews/index.json.jbuilder +6 -0
  32. data/app/views/spree/api/reviews/show.json.jbuilder +3 -0
  33. data/app/views/spree/feedback_reviews/_form.html.erb +5 -5
  34. data/app/views/spree/feedback_reviews/_summary.html.erb +3 -3
  35. data/app/views/spree/feedback_reviews/create.js.erb +2 -2
  36. data/app/views/spree/reviews/_form.html.erb +15 -10
  37. data/app/views/spree/reviews/new.html.erb +2 -2
  38. data/app/views/spree/shared/_rating.html.erb +3 -3
  39. data/app/views/spree/shared/_review.html.erb +29 -19
  40. data/app/views/spree/shared/_review_summary.html.erb +3 -3
  41. data/app/views/spree/shared/_reviews.html.erb +6 -6
  42. data/app/views/spree/shared/_shortrating.html.erb +2 -2
  43. data/bin/rails +4 -2
  44. data/config/initializers/constants.rb +2 -0
  45. data/config/initializers/load_preferences.rb +2 -0
  46. data/config/locales/de-CH.yml +14 -1
  47. data/config/locales/de.yml +14 -1
  48. data/config/locales/en-GB.yml +14 -2
  49. data/config/locales/en.yml +14 -1
  50. data/config/locales/es.yml +14 -2
  51. data/config/locales/fr.yml +14 -2
  52. data/config/locales/it.yml +79 -0
  53. data/config/locales/pl.yml +14 -2
  54. data/config/locales/pt-BR.yml +14 -2
  55. data/config/locales/pt.yml +14 -2
  56. data/config/locales/ro.yml +15 -3
  57. data/config/locales/ru.yml +14 -2
  58. data/config/locales/sv.yml +14 -1
  59. data/config/locales/tr.yml +14 -2
  60. data/config/locales/uk.yml +14 -1
  61. data/config/locales/zh-CN.yml +14 -1
  62. data/config/locales/zh-TW.yml +14 -1
  63. data/config/routes.rb +18 -1
  64. data/db/migrate/20081020220724_create_reviews.rb +4 -2
  65. data/db/migrate/20101222083309_create_feedback_reviews.rb +5 -3
  66. data/db/migrate/20110406083603_add_rating_to_products.rb +7 -5
  67. data/db/migrate/20110606150524_add_user_to_reviews.rb +4 -2
  68. data/db/migrate/20110806093221_add_ip_address_to_reviews.rb +3 -1
  69. data/db/migrate/20120110172331_namespace_tables.rb +3 -1
  70. data/db/migrate/20120123141326_recalculate_ratings.rb +6 -5
  71. data/db/migrate/20120712182514_add_locale_to_reviews.rb +4 -2
  72. data/db/migrate/20120712182627_add_locale_to_feedback_reviews.rb +4 -2
  73. data/db/migrate/20140703200946_add_show_identifier_to_reviews.rb +3 -1
  74. data/db/migrate/20190613165528_add_verified_purchaser_to_reviews.rb +5 -0
  75. data/lib/controllers/spree/api/reviews_controller.rb +111 -0
  76. data/lib/generators/solidus_reviews/install/install_generator.rb +5 -4
  77. data/lib/solidus_reviews.rb +3 -1
  78. data/lib/solidus_reviews/factories.rb +3 -1
  79. data/lib/solidus_reviews/factories/feedback_review_factory.rb +6 -5
  80. data/lib/solidus_reviews/factories/review_factory.rb +19 -9
  81. data/lib/spree_reviews/engine.rb +7 -0
  82. data/solidus_reviews.gemspec +20 -18
  83. data/spec/controllers/admin/feedback_reviews_controller_spec.rb +9 -7
  84. data/spec/controllers/admin/review_settings_controller_spec.rb +18 -16
  85. data/spec/controllers/admin/reviews_controller_spec.rb +18 -16
  86. data/spec/controllers/feedback_reviews_controller_spec.rb +29 -25
  87. data/spec/controllers/products_controller_spec.rb +4 -2
  88. data/spec/controllers/reviews_controller_spec.rb +67 -40
  89. data/spec/controllers/spree/api/reviews_controller_spec.rb +233 -0
  90. data/spec/features/admin_spec.rb +3 -0
  91. data/spec/features/reviews_spec.rb +27 -11
  92. data/spec/helpers/review_helper_spec.rb +3 -2
  93. data/spec/models/feedback_review_spec.rb +19 -17
  94. data/spec/models/product_spec.rb +41 -19
  95. data/spec/models/review_spec.rb +100 -42
  96. data/spec/models/reviews_ability_spec.rb +10 -8
  97. data/spec/models/reviews_configuration_spec.rb +28 -19
  98. data/spec/spec_helper.rb +21 -35
  99. data/vendor/assets/javascripts/jquery.rating.js +389 -376
  100. metadata +108 -59
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Spree::ProductsController do
4
6
  [:avg_rating, :reviews_count].each do |attrib|
5
7
  it "should add #{attrib} to the set of allowed attributes" do
6
- controller.permitted_product_attributes.should include(attrib)
8
+ expect(controller.permitted_product_attributes).to include(attrib)
7
9
  end
8
10
  end
9
- end
11
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe Spree::ReviewsController, type: :controller do
@@ -8,19 +10,24 @@ describe Spree::ReviewsController, type: :controller do
8
10
  review: { rating: 3,
9
11
  name: 'Ryan Bigg',
10
12
  title: 'Great Product',
11
- review: 'Some big review text..' } }
13
+ review: 'Some big review text..',
14
+ images: [
15
+ fixture_file_upload(File.new(Spree::Core::Engine.root + 'spec/fixtures/thinking-cat.jpg'))
16
+ ] }
17
+ }
12
18
  end
13
19
 
14
20
  before do
15
- controller.stub :spree_current_user => user
16
- controller.stub :spree_user_signed_in? => true
21
+ allow(controller).to receive(:spree_current_user).and_return(user)
22
+ allow(controller).to receive(:spree_user_signed_in?).and_return(true)
17
23
  end
18
24
 
19
25
  context '#index' do
20
26
  context 'for a product that does not exist' do
21
27
  it 'responds with a 404' do
22
- spree_get :index, product_id: 'not_real'
23
- response.status.should eq(404)
28
+ expect {
29
+ get :index, params: { product_id: 'not_real' }
30
+ }.to raise_error(ActiveRecord::RecordNotFound)
24
31
  end
25
32
  end
26
33
 
@@ -30,8 +37,8 @@ describe Spree::ReviewsController, type: :controller do
30
37
  create(:review, :approved, product: product),
31
38
  create(:review, :approved, product: product)
32
39
  ]
33
- spree_get :index, product_id: product.slug
34
- assigns[:approved_reviews].should =~ approved_reviews
40
+ get :index, params: { product_id: product.slug }
41
+ expect(assigns[:approved_reviews]).to match_array approved_reviews
35
42
  end
36
43
  end
37
44
  end
@@ -39,87 +46,107 @@ describe Spree::ReviewsController, type: :controller do
39
46
  context '#new' do
40
47
  context 'for a product that does not exist' do
41
48
  it 'responds with a 404' do
42
- spree_get :new, product_id: 'not_real'
43
- response.status.should eq(404)
49
+ expect {
50
+ get :new, params: { product_id: 'not_real' }
51
+ }.to raise_error(ActiveRecord::RecordNotFound)
44
52
  end
45
53
  end
46
54
 
47
55
  it 'fail if the user is not authorized to create a review' do
48
- controller.stub(:authorize!) { raise }
56
+ allow(controller).to receive(:authorize!).and_raise(RuntimeError)
57
+
49
58
  expect {
50
- spree_post :new, product_id: product.slug
59
+ post :new, params: { product_id: product.slug }
51
60
  assert_match 'ryanbig', response.body
52
- }.to raise_error
61
+ }.to raise_error RuntimeError
53
62
  end
54
63
 
55
64
  it 'render the new template' do
56
- spree_get :new, product_id: product.slug
57
- response.status.should eq(200)
58
- response.should render_template(:new)
65
+ get :new, params: { product_id: product.slug }
66
+ expect(response.status).to eq(200)
67
+ expect(response).to render_template(:new)
59
68
  end
60
69
  end
61
70
 
62
71
  context '#create' do
63
- before { controller.stub spree_current_user: user }
72
+ before { allow(controller).to receive(:spree_current_user).and_return(user) }
64
73
 
65
74
  context 'for a product that does not exist' do
66
75
  it 'responds with a 404' do
67
- spree_post :create, product_id: 'not_real'
68
- response.status.should eq(404)
76
+ expect {
77
+ post :create, params: { product_id: 'not_real' }
78
+ }.to raise_error(ActiveRecord::RecordNotFound)
69
79
  end
70
80
  end
71
81
 
72
82
  it 'creates a new review' do
73
83
  expect {
74
- spree_post :create, review_params
84
+ post :create, params: review_params
85
+ }.to change(Spree::Review, :count).by(1)
86
+ end
87
+
88
+ it 'creates a rating only review' do
89
+ review_params = {
90
+ product_id: product.slug,
91
+ review: { rating: 3 }
92
+ }
93
+
94
+ expect {
95
+ post :create, params: review_params
75
96
  }.to change(Spree::Review, :count).by(1)
76
97
  end
77
98
 
78
99
  it 'sets the ip-address of the remote' do
79
- request.stub(remote_ip: '127.0.0.1')
80
- spree_post :create, review_params
81
- assigns[:review].ip_address.should eq '127.0.0.1'
100
+ @request.env['REMOTE_ADDR'] = '127.0.0.1'
101
+ post :create, params: review_params
102
+ expect(assigns[:review].ip_address).to eq '127.0.0.1'
103
+ end
104
+
105
+ it 'attaches the image' do
106
+ post :create, params: review_params
107
+ expect(assigns[:review].images).to be_present
82
108
  end
83
109
 
84
110
  it 'fails if the user is not authorized to create a review' do
85
- controller.stub(:authorize!) { raise }
111
+ allow(controller).to receive(:authorize!).and_raise(RuntimeError)
112
+
86
113
  expect{
87
- spree_post :create, review_params
88
- }.to raise_error
114
+ post :create, params: review_params
115
+ }.to raise_error RuntimeError
89
116
  end
90
117
 
91
118
  it 'flashes the notice' do
92
- spree_post :create, review_params
93
- flash[:notice].should eq Spree.t(:review_successfully_submitted)
119
+ post :create, params: review_params
120
+ expect(flash[:notice]).to eq I18n.t('spree.review_successfully_submitted')
94
121
  end
95
122
 
96
123
  it 'redirects to product page' do
97
- spree_post :create, review_params
98
- response.should redirect_to spree.product_path(product)
124
+ post :create, params: review_params
125
+ expect(response).to redirect_to spree.product_path(product)
99
126
  end
100
127
 
101
128
  it 'removes all non-numbers from ratings param' do
102
- spree_post :create, review_params
103
- controller.params[:review][:rating].should eq '3'
129
+ post :create, params: review_params
130
+ expect(controller.params[:review][:rating]).to eq '3'
104
131
  end
105
132
 
106
133
  it 'sets the current spree user as reviews user' do
107
- spree_post :create, review_params
108
- review_params[:review].merge!(user_id: user.id)
134
+ post :create, params: review_params
135
+ review_params[:review][:user_id] = user.id
109
136
  assigns[:review][:user_id] = user.id
110
- assigns[:review][:user_id].should eq user.id
137
+ expect(assigns[:review][:user_id]).to eq user.id
111
138
  end
112
139
 
113
140
  context 'with invalid params' do
114
141
  it 'renders new when review.save fails' do
115
- Spree::Review.any_instance.stub(:save).and_return(false)
116
- spree_post :create, review_params
117
- response.should render_template :new
142
+ expect_any_instance_of(Spree::Review).to receive(:save).and_return(false)
143
+ post :create, params: review_params
144
+ expect(response).to render_template :new
118
145
  end
119
146
 
120
147
  it 'does not create a review' do
121
148
  expect(Spree::Review.count).to eq 0
122
- spree_post :create, review_params.merge({review: {rating: 'not_a_number'}})
149
+ post :create, params: review_params.merge({ review: { rating: 'not_a_number' } })
123
150
  expect(Spree::Review.count).to eq 0
124
151
  end
125
152
  end
@@ -128,8 +155,8 @@ describe Spree::ReviewsController, type: :controller do
128
155
  context 'when config requires locale tracking:' do
129
156
  it 'sets the locale' do
130
157
  Spree::Reviews::Config.preferred_track_locale = true
131
- spree_post :create, review_params
132
- assigns[:review].locale.should eq I18n.locale.to_s
158
+ post :create, params: review_params
159
+ expect(assigns[:review].locale).to eq I18n.locale.to_s
133
160
  end
134
161
  end
135
162
  end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Spree::Api::ReviewsController, type: :controller do
6
+ render_views
7
+
8
+ let!(:user) { create(:user) }
9
+ let!(:review) { create(:review, rating: 5) }
10
+ let!(:product) { review.product }
11
+
12
+ before do
13
+ user.generate_spree_api_key!
14
+ Array.new(3).each do
15
+ create(:review)
16
+ end
17
+ end
18
+
19
+ describe '#index' do
20
+ context 'when given a product_id' do
21
+ subject do
22
+ get :index, params: { product_id: product.id, token: user.spree_api_key, format: 'json' }
23
+ JSON.parse(response.body)
24
+ end
25
+
26
+ context 'there are no reviews for a product' do
27
+ it 'should return an empty array' do
28
+ expect(Spree::Review.count).to be >= 0
29
+ expect(subject["reviews"]).to be_empty
30
+ end
31
+ end
32
+
33
+ context 'there are reviews for the product and other products' do
34
+ it 'returns all approved reviews for the product' do
35
+ review.update(approved: true)
36
+ review.images << create(:image)
37
+ expect(Spree::Review.count).to be >= 2
38
+ expect(subject.size).to eq(2)
39
+ expect(subject["reviews"][0]["id"]).to eq(review.id)
40
+ expect(subject["reviews"][0]["images"].count).to eq(1)
41
+ expect(subject["avg_rating"]).to eq("5.0")
42
+ end
43
+ end
44
+ end
45
+
46
+ context 'when given a user_id' do
47
+ subject do
48
+ get :index, params: { user_id: user.id, token: user.spree_api_key, format: 'json' }
49
+ JSON.parse(response.body)
50
+ end
51
+
52
+ context 'there are no reviews for the user' do
53
+ it 'should return an empty array' do
54
+ expect(Spree::Review.count).to be >= 0
55
+ expect(subject["reviews"]).to be_empty
56
+ end
57
+ end
58
+
59
+ context 'there are reviews for user' do
60
+ before { review.update(user_id: user.id) }
61
+
62
+ it 'returns all reviews for the user' do
63
+ expect(Spree::Review.count).to be >= 2
64
+ expect(subject.size).to eq(2)
65
+ expect(subject["reviews"][0]["id"]).to eq(review.id)
66
+ expect(subject["avg_rating"]).to eq(nil)
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe '#show' do
73
+ subject do
74
+ get :show, params: { id: review.id, token: user.spree_api_key, format: 'json' }
75
+ JSON.parse(response.body)
76
+ end
77
+
78
+ context 'when it is the users review' do
79
+ before { review.update(user_id: user.id) }
80
+
81
+ it 'should return the review' do
82
+ expect(subject).not_to be_empty
83
+ expect(subject["product_id"]).to eq(product.id)
84
+ expect(subject["name"]).to eq(review[:name])
85
+ expect(subject["review"]).to eq(review[:review])
86
+ expect(subject["title"]).to eq(review[:title])
87
+ expect(subject["verified_purchaser"]).to eq(false)
88
+ expect(subject["images"]).to eq([])
89
+ expect(subject["feedback_reviews"]).to eq([])
90
+ end
91
+ end
92
+
93
+ context 'when it is not the users review' do
94
+ it 'should return with not authorized' do
95
+ expect(subject["error"]).not_to be_empty
96
+ expect(subject["error"]).to match(/not authorized/i)
97
+ end
98
+
99
+ context 'and it the review is approved' do
100
+ before { review.update(approved: true) }
101
+
102
+ it 'should return the review' do
103
+ expect(subject).not_to be_empty
104
+ expect(subject["product_id"]).to eq(product.id)
105
+ expect(subject["name"]).to eq(review[:name])
106
+ expect(subject["review"]).to eq(review[:review])
107
+ expect(subject["title"]).to eq(review[:title])
108
+ expect(subject["images"]).to eq([])
109
+ expect(subject["feedback_reviews"]).to eq([])
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ describe '#create' do
116
+ let(:review_params) do
117
+ {
118
+ "user_id": user.id,
119
+ "rating": "3 stars",
120
+ "title": "My title 2",
121
+ "name": "Full Name",
122
+ "review": "My review of the product"
123
+ }
124
+ end
125
+
126
+ subject do
127
+ params = { product_id: product.id, token: user.spree_api_key, format: 'json' }.merge(review_params)
128
+ post :create, params: params
129
+ JSON.parse(response.body)
130
+ end
131
+
132
+ context 'when user has already reviewed this product' do
133
+ before do
134
+ review.update(user_id: user.id)
135
+ end
136
+
137
+ it 'should return with a fail' do
138
+ expect(subject["error"]).not_to be_empty
139
+ expect(subject["error"]).to match(/invalid resource/i)
140
+ end
141
+ end
142
+
143
+ context 'when it is a users first review for the product' do
144
+ it 'should return success with review' do
145
+ expect(subject).not_to be_empty
146
+ expect(subject["product_id"]).to eq(product.id)
147
+ expect(subject["name"]).to eq(review_params[:name])
148
+ expect(subject["review"]).to eq(review_params[:review])
149
+ expect(subject["title"]).to eq(review_params[:title])
150
+ expect(subject["images"]).to eq([])
151
+ expect(subject["feedback_reviews"]).to eq([])
152
+ end
153
+ end
154
+ end
155
+
156
+ describe '#update' do
157
+ before { review.update(approved: true, user_id: user.id) }
158
+ let(:params) { { product_id: product.id, id: review.id, token: user.spree_api_key, format: 'json' }.merge(review_params) }
159
+
160
+ let(:review_params) do
161
+ {
162
+ "rating": "3 stars",
163
+ "title": "My title 2",
164
+ "name": "Full name",
165
+ "review": "My review of the product",
166
+ }
167
+ end
168
+
169
+ subject do
170
+ put :update, params: params
171
+ JSON.parse(response.body)
172
+ end
173
+
174
+ context 'when a user updates their own review' do
175
+ it 'should successfully update the review and set approved back to false' do
176
+ original = review
177
+ expect(original.approved?).to be true
178
+ expect(subject["id"]).to eq(original.id)
179
+ expect(subject["user_id"]).to eq(original.user_id)
180
+ expect(subject["product_id"]).to eq(original.product_id)
181
+ expect(subject["approved"]).to be false
182
+ expect(subject["images"]).to eq([])
183
+ expect(subject["feedback_reviews"]).to eq([])
184
+ end
185
+ end
186
+
187
+ context 'when a user updates another users review' do
188
+ let(:other_user) { create(:user) }
189
+ let(:params) { { product_id: product.id, id: review.id, token: other_user.spree_api_key, format: 'json' }.merge(review_params) }
190
+
191
+ before do
192
+ other_user.generate_spree_api_key!
193
+ end
194
+
195
+ it 'should return an error' do
196
+ expect(subject["error"]).not_to be_empty
197
+ expect(subject["error"]).to match(/not authorized/i)
198
+ end
199
+ end
200
+ end
201
+
202
+ describe '#destroy' do
203
+ before { review.update(approved: true, user_id: user.id) }
204
+ let(:params) { { product_id: product.id, id: review.id, token: user.spree_api_key, format: 'json' } }
205
+
206
+ subject do
207
+ delete :destroy, params: params
208
+ JSON.parse(response.body)
209
+ end
210
+
211
+ context "when a user destroys their own review" do
212
+ it 'should return the deleted review' do
213
+ expect(subject["id"]).to eq(review.id)
214
+ expect(subject["product_id"]).to eq(product.id)
215
+ expect(Spree::Review.find_by(id: review.id)).to be_falsey
216
+ end
217
+ end
218
+
219
+ context "when a user destroys another users review" do
220
+ let(:other_user) { create(:user) }
221
+ let(:params) { { product_id: product.id, id: review.id, token: other_user.spree_api_key, format: 'json' } }
222
+
223
+ before do
224
+ other_user.generate_spree_api_key!
225
+ end
226
+
227
+ it 'should return an error' do
228
+ expect(subject["error"]).not_to be_empty
229
+ expect(subject["error"]).to match(/not authorized/i)
230
+ end
231
+ end
232
+ end
233
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  RSpec.feature 'Review Admin' do
@@ -30,6 +32,7 @@ RSpec.feature 'Review Admin' do
30
32
 
31
33
  expect(page).to have_text 'Editing'
32
34
  expect(page).to have_text review.title
35
+ expect(page).to have_css('a', text: review.email)
33
36
  end
34
37
  end
35
38
  end