symphonia 3.4.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -4
  3. data/CHANGELOG.md +12 -0
  4. data/README.md +16 -0
  5. data/app/controllers/symphonia/admin_controller.rb +1 -4
  6. data/app/views/symphonia/admin/index.html.erb +1 -11
  7. data/db/migrate/20130714140501_create_roles.rb +6 -4
  8. data/db/migrate/20200428180001_add_uuid_to_users.rb +4 -2
  9. data/db/migrate/20210509141420_roles_change_permissions_to_json.rb +18 -0
  10. data/db/migrate/20210509180525_roles_change_permissions_to_native_json.rb +7 -0
  11. data/lib/generators/symphonia/setup/setup_generator.rb +17 -14
  12. data/lib/generators/symphonia/setup/templates/{settings.rb → app/config/initializers/settings.rb.tt} +0 -0
  13. data/lib/generators/symphonia/setup/templates/{404.html → public/404.html.tt} +2 -2
  14. data/lib/generators/symphonia/setup/templates/{500.html → public/500.html.tt} +2 -2
  15. data/lib/generators/symphonia/setup/templates/{spec_helper.rb → spec/spec_helper.rb.tt} +3 -2
  16. data/lib/symphonia.rb +4 -1
  17. data/lib/symphonia/model_attributes/attribute.rb +30 -14
  18. data/lib/symphonia/model_filters/base.rb +13 -15
  19. data/lib/symphonia/model_filters/boolean_filter.rb +10 -11
  20. data/lib/symphonia/model_filters/date_filter.rb +32 -31
  21. data/lib/symphonia/model_filters/integer_filter.rb +4 -5
  22. data/lib/symphonia/model_filters/select_filter.rb +19 -17
  23. data/lib/symphonia/model_filters/string_filter.rb +4 -5
  24. data/lib/symphonia/query.rb +10 -34
  25. data/lib/symphonia/query_columns.rb +1 -2
  26. data/lib/symphonia/query_columns/attribute_column.rb +59 -5
  27. data/lib/symphonia/spec_helper.rb +5 -3
  28. data/lib/symphonia/version.rb +3 -1
  29. data/spec/controllers/account_controller_spec.rb +66 -69
  30. data/spec/controllers/admin_controller_spec.rb +24 -25
  31. data/spec/libs/some_lib_spec.rb +1 -1
  32. data/spec/rails_helper.rb +4 -3
  33. data/spec/spec_helper.rb +3 -8
  34. metadata +71 -158
  35. data/app/models/symphonia/admin_module.rb +0 -18
  36. data/app/views/symphonia/filters/table.html.erb +0 -21
  37. data/db/migrate/20130828175114_create_attachments.rb +0 -20
  38. data/db/migrate/20141213204351_create_admin_modules.rb +0 -20
  39. data/lib/symphonia/query_columns/generic_column.rb +0 -165
@@ -2,12 +2,12 @@ module Symphonia
2
2
  module ModelFilters
3
3
  class BooleanFilter < Base
4
4
 
5
- def operator=(o)
6
- if o == '!'
7
- @operator = 'not_eq'
8
- else
9
- @operator = 'eq'
10
- end
5
+ def operator=(to)
6
+ @operator = if to == '!'
7
+ 'not_eq'
8
+ else
9
+ 'eq'
10
+ end
11
11
  end
12
12
 
13
13
  def apply(scope)
@@ -16,11 +16,10 @@ module Symphonia
16
16
  scope.where(t[name].send(operator, true))
17
17
  end
18
18
 
19
- def form_field(_c)
20
- _c.text_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
19
+ def form_field(context)
20
+ context.text_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
21
21
  end
22
- end
23
22
 
23
+ end
24
24
  end
25
-
26
- end
25
+ end
@@ -1,18 +1,18 @@
1
1
  module Symphonia
2
2
  module ModelFilters
3
3
  class DateFilter < Base
4
- attr_accessor :available_values
4
+ attr_writer :available_values
5
5
 
6
- def initialize(name, query, options={})
6
+ def initialize(name, query, options = {})
7
7
  super
8
8
  @operator = 'in'
9
9
  end
10
10
 
11
- def value=(q)
12
- v = available_values.values.reduce(:merge)[q.to_sym]
11
+ def value=(to)
12
+ v = available_values.values.reduce(:merge)[to.to_sym]
13
13
  @operator = 'between' unless q == 'today'
14
- @value = if q == 'custom'
15
- data = self.query.controller.params.require(:date_from_custom).permit(:from, :to)
14
+ @value = if to == 'custom'
15
+ data = query.controller.params.require(:date_from_custom).permit(:from, :to)
16
16
  v.call(data)
17
17
  else
18
18
  v.call
@@ -34,48 +34,49 @@ module Symphonia
34
34
  def available_values
35
35
  {
36
36
  past: {
37
- last_month: -> {d = Date.today.last_month.beginning_of_month; d..d.end_of_month},
38
- last_year: -> {d = Date.today.last_year.beginning_of_year; d..d.end_of_year}
37
+ last_month: -> { d = Date.today.last_month.beginning_of_month; d..d.end_of_month },
38
+ last_year: -> { d = Date.today.last_year.beginning_of_year; d..d.end_of_year },
39
39
  },
40
40
  present: {
41
- today: -> {Date.today},
42
- this_month: -> {Date.today.beginning_of_month..Date.today.end_of_month},
43
- this_year: -> {Date.today.beginning_of_year..Date.today.end_of_year},
44
- custom: ->(data) {data[:from].to_date..data[:to].to_date}
41
+ today: -> { Date.today },
42
+ this_month: -> { Date.today.beginning_of_month..Date.today.end_of_month },
43
+ this_year: -> { Date.today.beginning_of_year..Date.today.end_of_year },
44
+ custom: ->(data) { data[:from].to_date..data[:to].to_date },
45
45
  },
46
46
  future: {
47
- next_month: -> {d = Date.today.next_month.beginning_of_month; d..d.end_of_month},
48
- next_year: -> {d = Date.today.next_year.beginning_of_year; d..d.end_of_year}
49
- }
47
+ next_month: -> { d = Date.today.next_month.beginning_of_month; d..d.end_of_month },
48
+ next_year: -> { d = Date.today.next_year.beginning_of_year; d..d.end_of_year },
49
+ },
50
50
  }
51
51
  end
52
52
 
53
- def form_field(_c)
54
- groups = available_values.inject({}) do |mem, (time, values)|
55
- mem[_c.t("time.#{time}")] = values.collect do |(k, _val)|
56
- [_c.t("query_options.filter_date.values.#{k}"), k]
53
+ def form_field(context)
54
+ groups = available_values.each_with_object({}) do |(time, values), mem|
55
+ mem[context.t("time.#{time}")] = values.collect do |(k, _val)|
56
+ [context.t("query_options.filter_date.values.#{k}"), k]
57
57
  end
58
- mem
59
58
  end
60
59
  selected = Array(@query.active_filters[name])
61
- _c.content_tag(:div, class: 'row') do
62
- _c.select_tag("#{form_field_name}", _c.grouped_options_for_select(groups, selected), {
60
+ context.content_tag(:div, class: 'row') do
61
+ context.select_tag(form_field_name.to_s, context.grouped_options_for_select(groups, selected), {
63
62
  class: 'form-control',
64
63
  include_blank: true,
65
- onchange: 'symphoniaFiltersForm.dateFilterCallback(this)'
66
- }) + _c.content_tag(:div, class: 'filter-custom-date clearfix input-daterange input-group inline', style: 'display: none') do
67
- _c.date_field_tag("#{form_field_name}_custom[to]", '', {
68
- placeholder: _c.t('query_options.filter_date.to'),
69
- class: 'form-control datepicker pull-right'
64
+ onchange: 'symphoniaFiltersForm.dateFilterCallback(this)',
65
+ }) + context.content_tag(:div, class: 'filter-custom-date clearfix input-daterange input-group inline',
66
+ style: 'display: none') do
67
+ context.date_field_tag("#{form_field_name}contextustom[to]", '', {
68
+ placeholder: context.t('query_options.filter_date.to'),
69
+ class: 'form-control datepicker pull-right',
70
70
  }) +
71
- # _c.content_tag(:span, _c.t('query_options.filter_date.to'), class: 'input-group-addon')+
72
- _c.date_field_tag("#{form_field_name}_custom[from]", '', {
71
+ # context.content_tag(:span, context.t('query_options.filter_date.to'), class: 'input-group-addon')+
72
+ context.date_field_tag("#{form_field_name}_custom[from]", '', {
73
73
  placeholder: _c.t('query_options.filter_date.from'),
74
- class: 'form-control datepicker'
74
+ class: 'form-control datepicker',
75
75
  })
76
76
  end
77
77
  end
78
78
  end
79
+
79
80
  end
80
81
  end
81
- end
82
+ end
@@ -8,11 +8,10 @@ module Symphonia
8
8
  scope.where(t[name].send(operator, value.to_f))
9
9
  end
10
10
 
11
- def form_field(_c)
12
- _c.number_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
11
+ def form_field(context)
12
+ context.number_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
13
13
  end
14
- end
15
14
 
15
+ end
16
16
  end
17
-
18
- end
17
+ end
@@ -1,7 +1,7 @@
1
1
  module Symphonia
2
2
  module ModelFilters
3
3
  class SelectFilter < StringFilter
4
- attr_accessor :available_values
4
+ attr_writer :available_values
5
5
 
6
6
  def initialize(name, query, options = {})
7
7
  super
@@ -9,7 +9,7 @@ module Symphonia
9
9
  end
10
10
 
11
11
  def available_values
12
- return @available_values.call(_c, self) if @available_values.is_a? Proc
12
+ return @available_values.call(context, self) if @available_values.is_a? Proc
13
13
 
14
14
  @available_values || case @attribute
15
15
  when Symphonia::ModelAttributes::EnumAttribute
@@ -17,18 +17,16 @@ module Symphonia
17
17
  end
18
18
  end
19
19
 
20
- def value=(q)
21
- @value = if q.is_a?(Array)
22
- q
20
+ def value=(to)
21
+ @value = if to.is_a?(Array)
22
+ to
23
23
  else
24
- q.to_s.split("|")
24
+ to.to_s.split("|")
25
25
  end
26
26
  end
27
27
 
28
- def operator=(o)
29
- if o == '!'
30
- @operator = 'not_in'
31
- end
28
+ def operator=(to)
29
+ @operator = 'not_in' if to == '!'
32
30
  end
33
31
 
34
32
  def apply(scope)
@@ -37,16 +35,20 @@ module Symphonia
37
35
  scope.where(t[name].send(operator, value))
38
36
  end
39
37
 
40
- def form_field(_c)
38
+ def form_field(context)
41
39
  selected = Array(@query.active_filters[name])
42
- _c.content_tag(:div, class: 'input-group') do
43
- _c.content_tag(:div, class: 'input-group-prepend') do
44
- _c.content_tag(:span, _c.check_box_tag("o[#{form_field_name}]", '!', operator == 'not_in', title: 'Not In'), class: "input-group-text")
40
+ context.content_tag(:div, class: 'input-group') do
41
+ context.content_tag(:div, class: 'input-group-prepend') do
42
+ context.content_tag(:span,
43
+ context.check_box_tag("o[#{form_field_name}]", '!', operator == 'not_in', title: 'Not In'), class: "input-group-text")
45
44
  end +
46
- _c.select_tag("#{form_field_name}[]", _c.options_for_select(available_values, selected), class: 'form-control', include_blank: true, multiple: selected.size > 1) +
47
- _c.content_tag(:div, _c.link_to(_c.fa_icon('plus-square-o'), 'javascript:void(0)', onclick: "toggleMultiSelect($(this).closest('.input-group').find('select'))", title: I18n.t(:title_toggle_multiselect), class: "input-group-text"), class: 'input-group-append')
45
+ context.select_tag("#{form_field_name}[]", context.options_for_select(available_values, selected),
46
+ class: 'form-control', include_blank: true, multiple: selected.size > 1) +
47
+ context.content_tag(:div,
48
+ context.link_to(context.fa_icon('plus-square-o'), 'javascript:void(0)', onclick: "toggleMultiSelect($(this).closest('.input-group').find('select'))", title: I18n.t(:title_toggle_multiselect), class: "input-group-text"), class: 'input-group-append')
48
49
  end
49
50
  end
51
+
50
52
  end
51
53
  end
52
- end
54
+ end
@@ -8,11 +8,10 @@ module Symphonia
8
8
  scope.where(t[name].lower.send(operator, value&.downcase))
9
9
  end
10
10
 
11
- def form_field(_c)
12
- _c.text_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
11
+ def form_field(context)
12
+ context.text_field_tag(form_field_name, @query.active_filters[name], class: 'form-control')
13
13
  end
14
- end
15
14
 
15
+ end
16
16
  end
17
-
18
- end
17
+ end
@@ -1,6 +1,7 @@
1
1
  module Symphonia
2
2
  class SymphoniaQueryNotRegistered < StandardError
3
3
  end
4
+
4
5
  class FilterNotFound < StandardError
5
6
  end
6
7
 
@@ -108,10 +109,8 @@ module Symphonia
108
109
  @columns ||= column_names.map { |c| available_columns[c] }.compact
109
110
  end
110
111
 
111
- def render_filters
112
- (available_filters | filters).each do |filter|
113
- yield filter
114
- end
112
+ def render_filters(&block)
113
+ (available_filters | filters).each(&block)
115
114
  end
116
115
 
117
116
  def entity_scope
@@ -161,11 +160,16 @@ module Symphonia
161
160
  'symphonia/common/query'
162
161
  end
163
162
 
164
- def to_params(force = false)
163
+ # Serialize query to params
164
+ # @param [FalseClass] force use applied filters, even that wasn't before
165
+ # @return [Hash]
166
+ def to_params(force: false)
165
167
  if @q
166
168
  { q: @q }
167
169
  elsif @set_filter || force
168
- filters.each_with_object(set_filter: 1) { |var, mem| f, v = var; mem[f.send(:form_field_name).to_sym] = v; }
170
+ filters.inject(set_filter: 1) do |(f, v), mem|
171
+ mem[f.send(:form_field_name).to_sym] = v
172
+ end
169
173
  else
170
174
  {}
171
175
  end
@@ -175,7 +179,6 @@ module Symphonia
175
179
  "#<#{self.class.name} set_filter=#{@set_filter} >"
176
180
  end
177
181
 
178
-
179
182
  def available_filters
180
183
  self.active_filters ||= {}
181
184
  self.operators ||= {}
@@ -230,33 +233,6 @@ module Symphonia
230
233
  @default_column_names
231
234
  end
232
235
 
233
- def add_column(_type, name, options = {})
234
- @available_columns[name] = "Symphonia::QueryColumns::#{_type.to_s.classify}Column".constantize.new(name, self, options)
235
- end
236
-
237
- # aliases
238
-
239
- def add_generic_column(name, options = {})
240
- add_column(:generic, name, options)
241
- end
242
-
243
- def add_text_column(name, options = {})
244
- add_column(:text, name, options)
245
- end
246
-
247
- def add_price_column(name, options = {})
248
- add_column(:price, name, options)
249
- end
250
-
251
- def add_date_column(name, options = {})
252
- add_column(:date, name, options)
253
- end
254
-
255
- def add_boolean_column(name, options = {})
256
- add_column(:boolean, name, options)
257
- end
258
-
259
- #
260
236
  def add_attribute_column(attribute, options = {})
261
237
  @available_columns[attribute.name] = ::Symphonia::QueryColumns::AttributeColumn.new(attribute, self, options)
262
238
  end
@@ -1,8 +1,7 @@
1
- require_dependency('symphonia/query_columns/generic_column')
2
1
  require_dependency('symphonia/query_columns/attribute_column')
3
2
 
4
3
  module Symphonia
5
4
  module QueryColumns
6
5
 
7
6
  end
8
- end
7
+ end
@@ -1,14 +1,14 @@
1
1
  module Symphonia
2
2
  module QueryColumns
3
- class AttributeColumn < GenericColumn
3
+ class AttributeColumn
4
4
 
5
- attr_reader :attribute
5
+ attr_reader :attribute, :name, :query, :model, :includes, :preload, :joins
6
6
  attr_accessor :no_header, :sort_options
7
- attr_writer :header, :sort
7
+ attr_writer :header, :sort, :sort_column_name, :sort_definition
8
8
 
9
9
  delegate :default?, :title, to: :attribute
10
10
 
11
- def initialize(attribute, query, options={})
11
+ def initialize(attribute, query, options = {})
12
12
  @attribute = attribute
13
13
  @name = attribute.name
14
14
  @query = query
@@ -38,6 +38,60 @@ module Symphonia
38
38
  @attribute.format(view, entity)
39
39
  end
40
40
 
41
+ def summarize?
42
+ false
43
+ end
44
+
45
+ def header?
46
+ !(@header == false)
47
+ end
48
+
49
+ def sort?
50
+ !(@sort == false)
51
+ end
52
+
53
+ def sort_definition
54
+ return nil unless sort?
55
+
56
+ @sort_definition ||= SortableTable::SortColumnCustomDefinition.new(@name, { asc: "#{sort_column_name} asc", desc: "#{sort_column_name} desc" })
57
+ end
58
+
59
+ def value(entity)
60
+ entity.send(name)
61
+ end
62
+
63
+ def sum_value(view)
64
+ format_value(view, OpenStruct.new(name => sum))
65
+ end
66
+
67
+ def sum
68
+ return nil unless summarize?
69
+
70
+ @sum ||= query.entities.sum(name)
71
+ end
72
+
73
+ def css_classes
74
+ @name.to_s
75
+ end
76
+
77
+ def inspect
78
+ "#<#{self.class.name} name='#{name}' options=#{@options.inspect}>"
79
+ end
80
+
81
+ private
82
+
83
+ def t(*args)
84
+ I18n.translate(*args)
85
+ end
86
+
87
+ def l(*args)
88
+ I18n.localize(*args)
89
+ end
90
+
91
+ def sort_column_name
92
+ @sort_column_name.presence || [@model.table_name, @name].join('.')
93
+ end
94
+
41
95
  end
42
96
  end
43
- end
97
+ end
@@ -1,4 +1,6 @@
1
- require File.expand_path('../../../spec/spec_helper', __FILE__)
2
- Dir.glob(File.expand_path('../../../spec/{factories,support}/*.rb', __FILE__)).each do |file|
3
- require file
1
+ if Rails.env.test?
2
+ require File.expand_path('../../../spec/spec_helper', __FILE__)
3
+ Dir.glob(File.expand_path('../../../spec/{factories,support}/*.rb', __FILE__)).each do |file|
4
+ require file
5
+ end
4
6
  end
@@ -1,3 +1,5 @@
1
1
  module Symphonia
2
- VERSION = '3.4.0'
2
+
3
+ VERSION = '4.0.0'
4
+
3
5
  end
@@ -1,99 +1,96 @@
1
- module Symphonia
2
- RSpec.describe AccountsController do
1
+ RSpec.describe Symphonia::AccountsController do
3
2
 
4
- include ActiveJob::TestHelper
3
+ include ActiveJob::TestHelper
5
4
 
6
- routes { Symphonia::Engine.routes }
5
+ routes { Symphonia::Engine.routes }
7
6
 
8
- let(:regular_user) { FactoryBot.create(:user) }
7
+ let(:regular_user) { FactoryBot.create(:user) }
9
8
 
10
- context 'logged', logged: true do
11
- context '#update' do
9
+ context 'logged', logged: true do
10
+ context '#update' do
12
11
 
13
- it 'valid' do
14
- put :update, params: { user: { login: Faker::Internet.user_name } }
15
- expect(response).to redirect_to account_path
16
- end
17
-
18
- it 'invalid' do
19
- put :update, params: { user: { login: '' } }
20
- expect(response).to have_http_status :success
21
- end
12
+ it 'valid' do
13
+ put :update, params: { user: { login: Faker::Internet.user_name } }
14
+ expect(response).to redirect_to account_path
15
+ end
22
16
 
17
+ it 'invalid' do
18
+ put :update, params: { user: { login: '' } }
19
+ expect(response).to have_http_status :success
23
20
  end
24
21
 
25
22
  end
23
+ end
26
24
 
27
- context '#resend_activation' do
25
+ context '#resend_activation' do
28
26
 
29
- let(:email) { Faker::Internet.email }
30
- subject { get :resend_activation, params: { email: email } }
27
+ let(:email) { Faker::Internet.email }
28
+ subject { get :resend_activation, params: { email: email } }
31
29
 
32
- it 'non exist user' do
33
- is_expected.to redirect_to :root
34
- expect(flash[:error]).not_to be :blank
35
- end
30
+ it 'non exist user' do
31
+ is_expected.to redirect_to :root
32
+ expect(flash[:error]).not_to be :blank
33
+ end
36
34
 
37
- it 'active user' do
38
- _user = FactoryBot.create(:user, email: email, status: 'active')
39
- is_expected.to redirect_to :root
40
- expect(flash[:error]).not_to be :blank
41
- end
35
+ it 'active user' do
36
+ _user = FactoryBot.create(:user, email: email, status: 'active')
37
+ is_expected.to redirect_to :root
38
+ expect(flash[:error]).not_to be :blank
39
+ end
42
40
 
43
- it 'pending user' do
44
- user = FactoryBot.create(:user, email: email, status: 'pending')
45
- token = user.perishable_token.dup
41
+ it 'pending user' do
42
+ user = FactoryBot.create(:user, email: email, status: 'pending')
43
+ token = user.perishable_token.dup
46
44
 
47
- expect { get :resend_activation, params: { email: email } }.to have_enqueued_job.on_queue('mailers')
48
- expect(response).to have_http_status :redirect
45
+ expect { get :resend_activation, params: { email: email } }.to have_enqueued_job.on_queue('mailers')
46
+ expect(response).to have_http_status :redirect
49
47
 
50
- expect(user.reload.perishable_token).not_to eq token
51
- expect(flash[:error]).to be_nil
52
- expect(flash[:notice]).not_to be :blank
53
- end
48
+ expect(user.reload.perishable_token).not_to eq token
49
+ expect(flash[:error]).to be_nil
50
+ expect(flash[:notice]).not_to be :blank
54
51
  end
52
+ end
55
53
 
56
- context '#activation' do
57
- let(:token) { SecureRandom.hex(3) }
58
- subject { get :activation, params: { activation_code: token } }
59
-
60
- it 'valid token' do
61
- user = FactoryBot.create(:user, status: 'pending')
62
- user.update_columns(perishable_token: token)
63
- is_expected.to redirect_to :login
64
- expect(user.reload.status).to eq 'active'
65
- end
54
+ context '#activation' do
55
+ let(:token) { SecureRandom.hex(3) }
56
+ subject { get :activation, params: { activation_code: token } }
66
57
 
67
- it 'invalid token' do
68
- is_expected.to redirect_to :root
69
- expect(flash[:error]).not_to be :blank
70
- end
58
+ it 'valid token' do
59
+ user = FactoryBot.create(:user, status: 'pending')
60
+ user.update_columns(perishable_token: token)
61
+ is_expected.to redirect_to :login
62
+ expect(user.reload.status).to eq 'active'
71
63
  end
72
64
 
73
- context '#lost_password' do
65
+ it 'invalid token' do
66
+ is_expected.to redirect_to :root
67
+ expect(flash[:error]).not_to be :blank
68
+ end
69
+ end
74
70
 
75
- it 'with mail' do
76
- user = FactoryBot.create(:user, status: 'active')
71
+ context '#lost_password' do
77
72
 
78
- expect { post :lost_password, params: { email: user.email } }.to have_enqueued_job.on_queue('mailers')
79
- expect(flash[:error]).to be_nil
80
- end
73
+ it 'with mail' do
74
+ user = FactoryBot.create(:user, status: 'active')
81
75
 
82
- it 'with inactive user' do
83
- user = FactoryBot.create(:user, status: 'pending')
84
- expect { post :lost_password, params: { email: user.email } }.not_to have_enqueued_job.on_queue('mailers')
85
- expect(flash[:error]).not_to be :blank
86
- end
76
+ expect { post :lost_password, params: { email: user.email } }.to have_enqueued_job.on_queue('mailers')
77
+ expect(flash[:error]).to be_nil
87
78
  end
88
79
 
89
- context "#reset_password" do
90
- subject { FactoryBot.create :user }
91
- it "reset" do
92
- put :reset_password, params: { id: subject.perishable_token, password: "secret-pass-1" }
93
- expect(response).to redirect_to /login/
94
- expect { subject.reload }.to change(subject, :crypted_password)
95
- end
80
+ it 'with inactive user' do
81
+ user = FactoryBot.create(:user, status: 'pending')
82
+ expect { post :lost_password, params: { email: user.email } }.not_to have_enqueued_job.on_queue('mailers')
83
+ expect(flash[:error]).not_to be :blank
96
84
  end
85
+ end
97
86
 
87
+ context "#reset_password" do
88
+ subject { FactoryBot.create :user }
89
+ it "reset" do
90
+ put :reset_password, params: { id: subject.perishable_token, password: "secret-pass-1" }
91
+ expect(response).to redirect_to /login/
92
+ expect { subject.reload }.to change(subject, :crypted_password)
93
+ end
98
94
  end
95
+
99
96
  end