symphonia 3.4.0 → 4.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.
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