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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -4
- data/CHANGELOG.md +12 -0
- data/README.md +16 -0
- data/app/controllers/symphonia/admin_controller.rb +1 -4
- data/app/views/symphonia/admin/index.html.erb +1 -11
- data/db/migrate/20130714140501_create_roles.rb +6 -4
- data/db/migrate/20200428180001_add_uuid_to_users.rb +4 -2
- data/db/migrate/20210509141420_roles_change_permissions_to_json.rb +18 -0
- data/db/migrate/20210509180525_roles_change_permissions_to_native_json.rb +7 -0
- data/lib/generators/symphonia/setup/setup_generator.rb +17 -14
- data/lib/generators/symphonia/setup/templates/{settings.rb → app/config/initializers/settings.rb.tt} +0 -0
- data/lib/generators/symphonia/setup/templates/{404.html → public/404.html.tt} +2 -2
- data/lib/generators/symphonia/setup/templates/{500.html → public/500.html.tt} +2 -2
- data/lib/generators/symphonia/setup/templates/{spec_helper.rb → spec/spec_helper.rb.tt} +3 -2
- data/lib/symphonia.rb +4 -1
- data/lib/symphonia/model_attributes/attribute.rb +30 -14
- data/lib/symphonia/model_filters/base.rb +13 -15
- data/lib/symphonia/model_filters/boolean_filter.rb +10 -11
- data/lib/symphonia/model_filters/date_filter.rb +32 -31
- data/lib/symphonia/model_filters/integer_filter.rb +4 -5
- data/lib/symphonia/model_filters/select_filter.rb +19 -17
- data/lib/symphonia/model_filters/string_filter.rb +4 -5
- data/lib/symphonia/query.rb +10 -34
- data/lib/symphonia/query_columns.rb +1 -2
- data/lib/symphonia/query_columns/attribute_column.rb +59 -5
- data/lib/symphonia/spec_helper.rb +5 -3
- data/lib/symphonia/version.rb +3 -1
- data/spec/controllers/account_controller_spec.rb +66 -69
- data/spec/controllers/admin_controller_spec.rb +24 -25
- data/spec/libs/some_lib_spec.rb +1 -1
- data/spec/rails_helper.rb +4 -3
- data/spec/spec_helper.rb +3 -8
- metadata +71 -158
- data/app/models/symphonia/admin_module.rb +0 -18
- data/app/views/symphonia/filters/table.html.erb +0 -21
- data/db/migrate/20130828175114_create_attachments.rb +0 -20
- data/db/migrate/20141213204351_create_admin_modules.rb +0 -20
- 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=(
|
6
|
-
if
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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(
|
20
|
-
|
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
|
-
|
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=(
|
12
|
-
v = available_values.values.reduce(:merge)[
|
11
|
+
def value=(to)
|
12
|
+
v = available_values.values.reduce(:merge)[to.to_sym]
|
13
13
|
@operator = 'between' unless q == 'today'
|
14
|
-
@value = if
|
15
|
-
data =
|
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(
|
54
|
-
groups = available_values.
|
55
|
-
mem[
|
56
|
-
[
|
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
|
-
|
62
|
-
|
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
|
-
}) +
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
#
|
72
|
-
|
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(
|
12
|
-
|
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
|
-
|
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(
|
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=(
|
21
|
-
@value = if
|
22
|
-
|
20
|
+
def value=(to)
|
21
|
+
@value = if to.is_a?(Array)
|
22
|
+
to
|
23
23
|
else
|
24
|
-
|
24
|
+
to.to_s.split("|")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def operator=(
|
29
|
-
if
|
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(
|
38
|
+
def form_field(context)
|
41
39
|
selected = Array(@query.active_filters[name])
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
47
|
-
|
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(
|
12
|
-
|
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
|
data/lib/symphonia/query.rb
CHANGED
@@ -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
|
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
|
-
|
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.
|
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,14 +1,14 @@
|
|
1
1
|
module Symphonia
|
2
2
|
module QueryColumns
|
3
|
-
class AttributeColumn
|
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
|
-
|
2
|
-
|
3
|
-
|
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
|
data/lib/symphonia/version.rb
CHANGED
@@ -1,99 +1,96 @@
|
|
1
|
-
|
2
|
-
RSpec.describe AccountsController do
|
1
|
+
RSpec.describe Symphonia::AccountsController do
|
3
2
|
|
4
|
-
|
3
|
+
include ActiveJob::TestHelper
|
5
4
|
|
6
|
-
|
5
|
+
routes { Symphonia::Engine.routes }
|
7
6
|
|
8
|
-
|
7
|
+
let(:regular_user) { FactoryBot.create(:user) }
|
9
8
|
|
10
|
-
|
11
|
-
|
9
|
+
context 'logged', logged: true do
|
10
|
+
context '#update' do
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
25
|
+
context '#resend_activation' do
|
28
26
|
|
29
|
-
|
30
|
-
|
27
|
+
let(:email) { Faker::Internet.email }
|
28
|
+
subject { get :resend_activation, params: { email: email } }
|
31
29
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
41
|
+
it 'pending user' do
|
42
|
+
user = FactoryBot.create(:user, email: email, status: 'pending')
|
43
|
+
token = user.perishable_token.dup
|
46
44
|
|
47
|
-
|
48
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
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
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
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
|
-
|
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
|
-
|
76
|
-
user = FactoryBot.create(:user, status: 'active')
|
71
|
+
context '#lost_password' do
|
77
72
|
|
78
|
-
|
79
|
-
|
80
|
-
end
|
73
|
+
it 'with mail' do
|
74
|
+
user = FactoryBot.create(:user, status: 'active')
|
81
75
|
|
82
|
-
|
83
|
-
|
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
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|