card 1.16.12 → 1.16.13
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/VERSION +1 -1
- data/card.gemspec +1 -1
- data/db/migrate_core_cards/20130823192433_add_style_cards.rb +39 -24
- data/db/migrate_core_cards/20140629222005_add_email_cards.rb +6 -11
- data/db/migrate_core_cards/20151120180631_add_token_expiration.rb +7 -0
- data/db/seed/new/card_actions.yml +396 -388
- data/db/seed/new/card_acts.yml +1 -595
- data/db/seed/new/card_changes.yml +8154 -23619
- data/db/seed/new/card_references.yml +1009 -988
- data/db/seed/new/cards.yml +1445 -1423
- data/db/seed/test/fixtures/card_actions.yml +1375 -1399
- data/db/seed/test/fixtures/card_acts.yml +445 -1063
- data/db/seed/test/fixtures/card_changes.yml +11440 -26881
- data/db/seed/test/fixtures/card_references.yml +1523 -1502
- data/db/seed/test/fixtures/cards.yml +2736 -2715
- data/db/seed/test/seed.rb +7 -10
- data/db/version_core_cards.txt +1 -1
- data/lib/card/auth.rb +65 -19
- data/lib/card/cache.rb +18 -18
- data/lib/card/env.rb +10 -10
- data/lib/card/format.rb +41 -30
- data/lib/card/location.rb +3 -5
- data/lib/card/subcards.rb +0 -3
- data/lib/card/success.rb +14 -11
- data/mod/01_core/set/all/subcards.rb +4 -2
- data/mod/01_core/set/all/trash.rb +4 -1
- data/mod/02_basic_types/set/type/pointer.rb +5 -2
- data/mod/05_email/set/all/notify.rb +85 -73
- data/mod/05_email/spec/set/all/notify_spec.rb +74 -55
- data/mod/05_standard/set/all/comment.rb +18 -12
- data/mod/05_standard/set/all/error.rb +5 -1
- data/mod/05_standard/set/right/account.rb +50 -73
- data/mod/05_standard/set/right/token.rb +49 -2
- data/mod/05_standard/set/self/signin.rb +14 -12
- data/mod/05_standard/set/type/signup.rb +17 -21
- data/mod/05_standard/spec/set/all/account_spec.rb +1 -1
- data/mod/05_standard/spec/set/right/account_spec.rb +76 -52
- data/mod/05_standard/spec/set/right/password_spec.rb +10 -11
- data/mod/05_standard/spec/set/right/token_spec.rb +19 -1
- data/mod/05_standard/spec/set/type/signup_spec.rb +3 -4
- data/spec/lib/card/auth_spec.rb +46 -5
- metadata +5 -4
@@ -31,7 +31,9 @@ def clear_subcards
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def unfilled?
|
34
|
-
(content.empty? || content.strip.empty?) &&
|
34
|
+
(content.empty? || content.strip.empty?) &&
|
35
|
+
(comment.blank? || comment.strip.blank?) &&
|
36
|
+
!subcards.present?
|
35
37
|
end
|
36
38
|
|
37
39
|
event :reject_empty_subcards, after: :approve, on: :save do
|
@@ -67,4 +69,4 @@ event :store_subcards, after: :store do
|
|
67
69
|
# eg. <user> creates <user+*account> creates <user+*account+*status>
|
68
70
|
# <user> changes <user+*account+*status> in event activate_account
|
69
71
|
Card.write_to_local_cache self
|
70
|
-
end
|
72
|
+
end
|
@@ -28,7 +28,10 @@ event :validate_delete, before: :approve, on: :delete do
|
|
28
28
|
errors.add :delete, "#{name} is is a system card. (#{codename})"
|
29
29
|
end
|
30
30
|
|
31
|
-
undeletable_all_rules_tags =
|
31
|
+
undeletable_all_rules_tags =
|
32
|
+
%w{ default style layout create read update delete }
|
33
|
+
# FIXME: HACK! should be configured in the rule
|
34
|
+
|
32
35
|
if junction? && (l = left) && l.codename == 'all' &&
|
33
36
|
undeletable_all_rules_tags.member?(right.codename)
|
34
37
|
errors.add :delete, "#{name} is an indestructible rule"
|
@@ -1,7 +1,10 @@
|
|
1
1
|
|
2
|
+
|
2
3
|
event :add_and_drop_items, before: :approve, on: :save do
|
3
|
-
|
4
|
-
|
4
|
+
adds = Env.params['add_item']
|
5
|
+
drops = Env.params['drop_item']
|
6
|
+
Array.wrap(adds).each { |i| add_item i } if adds
|
7
|
+
Array.wrap(drops).each { |i| drop_item i } if drops
|
5
8
|
end
|
6
9
|
|
7
10
|
event :insert_item_event, before: :approve, on: :save, when: proc {|c| Env.params['insert_item']} do
|
@@ -1,37 +1,30 @@
|
|
1
1
|
|
2
2
|
class FollowerStash
|
3
3
|
def initialize card=nil
|
4
|
-
@followed_affected_cards = Hash.new { |h,v| h[v]=[] }
|
4
|
+
@followed_affected_cards = Hash.new { |h, v| h[v] = [] }
|
5
5
|
@visited = ::Set.new
|
6
6
|
add_affected_card(card) if card
|
7
7
|
end
|
8
8
|
|
9
9
|
def add_affected_card card
|
10
|
+
return if @visited.include? card.key
|
10
11
|
Auth.as_bot do
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
if
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
if !@visited.intersection(includee_set).empty?
|
25
|
-
add_affected_card card.left
|
26
|
-
break
|
27
|
-
end
|
28
|
-
end
|
12
|
+
@visited.add card.key
|
13
|
+
notify_direct_followers card
|
14
|
+
return if !(left_card = card.left) || @visited.include?(left_card.key) ||
|
15
|
+
!(follow_field_rule = left_card.rule_card(:follow_fields))
|
16
|
+
follow_field_rule.item_names(context: left_card.cardname).each do |item|
|
17
|
+
if @visited.include? item.to_name.key
|
18
|
+
add_affected_card left_card
|
19
|
+
break
|
20
|
+
elsif item.to_name.key == Card[:includes].key
|
21
|
+
includee_set = Card.search(included_by: left_card.name).map(&:key)
|
22
|
+
if !@visited.intersection(includee_set).empty?
|
23
|
+
add_affected_card left_card
|
24
|
+
break
|
29
25
|
end
|
30
|
-
|
31
26
|
end
|
32
|
-
|
33
27
|
end
|
34
|
-
|
35
28
|
end
|
36
29
|
end
|
37
30
|
|
@@ -39,73 +32,86 @@ class FollowerStash
|
|
39
32
|
@followed_affected_cards.keys
|
40
33
|
end
|
41
34
|
|
42
|
-
def each_follower_with_reason
|
35
|
+
def each_follower_with_reason
|
36
|
+
# "follower"(=user) is a card object, "followed"(=reasons) a card name
|
43
37
|
@followed_affected_cards.each do |user, reasons|
|
44
|
-
yield(user,reasons.first)
|
38
|
+
yield(user, reasons.first)
|
45
39
|
end
|
46
40
|
end
|
47
41
|
|
48
42
|
private
|
49
43
|
|
44
|
+
def notify_direct_followers card
|
45
|
+
card.all_direct_follower_ids_with_reason do |user_id, reason|
|
46
|
+
notify Card.fetch(user_id), of: reason
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
50
|
def notify follower, because
|
51
51
|
@followed_affected_cards[follower] << because[:of]
|
52
52
|
end
|
53
|
-
|
54
53
|
end
|
55
54
|
|
56
55
|
def act_card
|
57
56
|
@supercard || self
|
58
57
|
end
|
59
58
|
|
60
|
-
|
61
59
|
def followable?
|
62
60
|
true
|
63
61
|
end
|
64
62
|
|
63
|
+
def silent_change?
|
64
|
+
silent_change.nil? ? !Card::Env[:controller] : silent_change
|
65
|
+
end
|
66
|
+
|
65
67
|
def notable_change?
|
66
|
-
!silent_change && !supercard && current_act &&
|
68
|
+
!silent_change? && !supercard && current_act &&
|
69
|
+
Card::Auth.current_id != WagnBotID && followable?
|
67
70
|
end
|
68
71
|
|
69
|
-
event :notify_followers_after_save,
|
72
|
+
event :notify_followers_after_save,
|
73
|
+
after: :subsequent, on: :save, when: proc { |ca| ca.notable_change? } do
|
70
74
|
notify_followers
|
71
75
|
end
|
72
76
|
|
73
77
|
# in the delete case we have to calculate the follower_stash beforehand
|
74
78
|
# but we can't pass the follower_stash through the ActiveJob queue.
|
75
|
-
# We have to deal with the notifications in the extend phase instead of the
|
79
|
+
# We have to deal with the notifications in the extend phase instead of the
|
80
|
+
# subsequent phase
|
76
81
|
event :stash_followers, after: :approve, on: :delete do
|
77
|
-
act_card.follower_stash ||=
|
82
|
+
act_card.follower_stash ||= FollowerStash.new
|
78
83
|
act_card.follower_stash.add_affected_card self
|
79
84
|
end
|
80
|
-
event :notify_followers_after_delete,
|
81
|
-
|
85
|
+
event :notify_followers_after_delete,
|
86
|
+
after: :extend, on: :delete, when: proc { |ca| ca.notable_change? } do
|
82
87
|
notify_followers
|
83
88
|
end
|
84
89
|
|
85
90
|
def notify_followers
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
@
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
end
|
91
|
+
@current_act.reload
|
92
|
+
@follower_stash ||= FollowerStash.new
|
93
|
+
@current_act.actions.each do |a|
|
94
|
+
@follower_stash.add_affected_card a.card if a.card
|
95
|
+
end
|
96
|
+
@follower_stash.each_follower_with_reason do |follower, reason|
|
97
|
+
if follower.account && follower != @current_act.actor
|
98
|
+
follower.account.send_change_notice @current_act, reason[:set_card].name,
|
99
|
+
reason[:option]
|
96
100
|
end
|
97
|
-
rescue =>e #this error handling should apply to all extend callback exceptions
|
98
|
-
Rails.logger.info "\nController exception: #{e.message}"
|
99
|
-
Card::Error.current = e
|
100
|
-
notable_exception_raised
|
101
101
|
end
|
102
|
+
# this error handling should apply to all extend callback exceptions
|
103
|
+
rescue => e
|
104
|
+
Rails.logger.info "\nController exception: #{e.message}"
|
105
|
+
Card::Error.current = e
|
106
|
+
notable_exception_raised
|
102
107
|
end
|
103
108
|
|
104
109
|
format do
|
105
110
|
view :list_of_changes, denial: :blank do |args|
|
106
111
|
action = get_action(args)
|
107
112
|
|
108
|
-
relevant_fields =
|
113
|
+
relevant_fields =
|
114
|
+
case action.action_type
|
109
115
|
when :create then [:cardtype, :content]
|
110
116
|
when :update then [:name, :cardtype, :content]
|
111
117
|
when :delete then [:content]
|
@@ -116,12 +122,12 @@ format do
|
|
116
122
|
end.compact.join
|
117
123
|
end
|
118
124
|
|
119
|
-
|
120
125
|
view :subedits, perms: :none do |args|
|
121
126
|
subedits =
|
122
127
|
get_act(args).relevant_actions_for(card).map do |action|
|
123
128
|
if action.card_id != card.id
|
124
|
-
action.card.format(format: @format)
|
129
|
+
action.card.format(format: @format)
|
130
|
+
.render_subedit_notice(action: action)
|
125
131
|
end
|
126
132
|
end.compact.join
|
127
133
|
|
@@ -134,16 +140,19 @@ format do
|
|
134
140
|
|
135
141
|
view :subedit_notice, denial: :blank do |args|
|
136
142
|
action = get_action(args)
|
137
|
-
name_before_action =
|
143
|
+
name_before_action =
|
144
|
+
(action.new_values[:name] && action.old_values[:name]) || card.name
|
138
145
|
|
139
146
|
wrap_subedit_item %{#{name_before_action} #{action.action_type}d
|
140
147
|
#{ render_list_of_changes(args) }}
|
141
148
|
end
|
142
149
|
|
143
150
|
view :followed, perms: :none, closed: true do |args|
|
144
|
-
if args[:followed_set] &&
|
145
|
-
|
146
|
-
|
151
|
+
if args[:followed_set] &&
|
152
|
+
(set_card = Card.fetch(args[:followed_set])) &&
|
153
|
+
args[:follow_option] &&
|
154
|
+
(option_card = Card.fetch(args[:follow_option]))
|
155
|
+
option_card.description set_card
|
147
156
|
else
|
148
157
|
'followed card'
|
149
158
|
end
|
@@ -154,23 +163,29 @@ format do
|
|
154
163
|
end
|
155
164
|
|
156
165
|
view :unfollow_url, perms: :none, closed: true do |args|
|
157
|
-
if args[:followed_set] && (set_card = Card.fetch(args[:followed_set])) &&
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
166
|
+
if args[:followed_set] && (set_card = Card.fetch(args[:followed_set])) &&
|
167
|
+
args[:follow_option] && args[:follower]
|
168
|
+
rule_name = set_card.follow_rule_name args[:follower]
|
169
|
+
target_name = "#{args[:follower]}+#{Card[:follow].name}"
|
170
|
+
update_path = page_path target_name,
|
171
|
+
action: :update,
|
172
|
+
card: { subcards: {
|
173
|
+
rule_name => Card[:never].name
|
174
|
+
} }
|
175
|
+
card_url update_path # absolutize path
|
162
176
|
end
|
163
177
|
end
|
164
178
|
|
165
179
|
def edit_info_for field, action
|
166
180
|
return nil unless action.new_values[field]
|
167
181
|
|
168
|
-
item_title =
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
182
|
+
item_title =
|
183
|
+
case action.action_type
|
184
|
+
when :update then 'new '
|
185
|
+
when :delete then 'deleted '
|
186
|
+
else ''
|
187
|
+
end
|
188
|
+
item_title += "#{field}: "
|
174
189
|
|
175
190
|
item_value =
|
176
191
|
if action.action_type == :delete
|
@@ -179,18 +194,20 @@ format do
|
|
179
194
|
action.new_values[field]
|
180
195
|
end
|
181
196
|
|
182
|
-
|
197
|
+
wrap_list_item "#{item_title}#{item_value}"
|
183
198
|
end
|
184
199
|
|
185
200
|
def get_act args
|
186
|
-
@notification_act ||= args[:act] ||
|
201
|
+
@notification_act ||= args[:act] ||
|
202
|
+
(args[:act_id] && Act.find(args[:act_id])) ||
|
203
|
+
card.acts.last
|
187
204
|
end
|
188
205
|
|
189
206
|
def get_action args
|
190
|
-
args[:action] || (args[:action_id]
|
207
|
+
args[:action] || (args[:action_id] && Action.fetch(args[:action_id])) ||
|
208
|
+
card.last_action
|
191
209
|
end
|
192
210
|
|
193
|
-
|
194
211
|
def wrap_subedits subedits
|
195
212
|
"\nThis update included the following changes:#{wrap_list subedits}"
|
196
213
|
end
|
@@ -208,7 +225,6 @@ format do
|
|
208
225
|
end
|
209
226
|
end
|
210
227
|
|
211
|
-
|
212
228
|
format :email_text do
|
213
229
|
view :last_action, perms: :none do |args|
|
214
230
|
act = get_act(args)
|
@@ -234,7 +250,3 @@ format :email_html do
|
|
234
250
|
"<li>#{text}</li>\n"
|
235
251
|
end
|
236
252
|
end
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
@@ -15,7 +15,11 @@ shared_examples_for 'notifications' do
|
|
15
15
|
it { is_expected.to include 'cardtype: Basic' }
|
16
16
|
end
|
17
17
|
context 'for a updated card' do
|
18
|
-
before
|
18
|
+
before do
|
19
|
+
@card.update_attributes!(
|
20
|
+
name: 'bnn card', type: :pointer, content: 'changed content'
|
21
|
+
)
|
22
|
+
end
|
19
23
|
it { is_expected.to include 'new content: [[changed content]]' }
|
20
24
|
it { is_expected.to include 'new cardtype: Pointer' }
|
21
25
|
it { is_expected.to include 'new name: bnn card' }
|
@@ -28,7 +32,9 @@ shared_examples_for 'notifications' do
|
|
28
32
|
context 'for a given action' do
|
29
33
|
subject do
|
30
34
|
action = @card.last_action
|
31
|
-
@card.update_attributes!(
|
35
|
+
@card.update_attributes!(
|
36
|
+
name: 'bnn card', type: :pointer, content: 'changed content'
|
37
|
+
)
|
32
38
|
@card.format(format: format).render_list_of_changes(action: action)
|
33
39
|
end
|
34
40
|
it { is_expected.to include "content: #{content}" }
|
@@ -36,8 +42,11 @@ shared_examples_for 'notifications' do
|
|
36
42
|
context 'for a given action id' do
|
37
43
|
subject do
|
38
44
|
action_id = @card.last_action.id
|
39
|
-
@card.update_attributes!(
|
40
|
-
|
45
|
+
@card.update_attributes!(
|
46
|
+
name: 'bnn card', type: :pointer, content: 'changed content'
|
47
|
+
)
|
48
|
+
@card.format(format: format)
|
49
|
+
.render_list_of_changes(action_id: action_id)
|
41
50
|
end
|
42
51
|
it { is_expected.to include "content: #{content}" }
|
43
52
|
end
|
@@ -63,7 +72,9 @@ shared_examples_for 'notifications' do
|
|
63
72
|
context 'for a updated card' do
|
64
73
|
changed_name = 'changed subedit notice'
|
65
74
|
changed_content = 'changed content'
|
66
|
-
before
|
75
|
+
before do
|
76
|
+
@card.update_attributes!(name: changed_name, content: changed_content)
|
77
|
+
end
|
67
78
|
it { is_expected.to include changed_name }
|
68
79
|
it { is_expected.to include 'updated' }
|
69
80
|
it { is_expected.to include list_of_changes_for @card }
|
@@ -77,13 +88,15 @@ shared_examples_for 'notifications' do
|
|
77
88
|
end
|
78
89
|
end
|
79
90
|
|
80
|
-
|
81
91
|
describe Card::Set::All::Notify do
|
92
|
+
before do
|
93
|
+
::Card.any_instance.stub(:'silent_change?').and_return(false)
|
94
|
+
end
|
82
95
|
|
83
96
|
describe 'content of notification email' do
|
84
97
|
context 'for new card with subcards' do
|
85
|
-
name =
|
86
|
-
content =
|
98
|
+
name = 'another card with subcards'
|
99
|
+
content = 'main content {{+s1}} {{+s2}}'
|
87
100
|
sub1_content = 'new content of subcard 1'
|
88
101
|
sub2_content = 'new content of subcard 2'
|
89
102
|
before do
|
@@ -110,9 +123,10 @@ describe Card::Set::All::Notify do
|
|
110
123
|
context 'and missing permissions' do
|
111
124
|
context 'for subcard' do
|
112
125
|
before do
|
113
|
-
Card.create_or_update! "#{name}+s1+*self+*read",
|
126
|
+
Card.create_or_update! "#{name}+s1+*self+*read",
|
127
|
+
type: 'Pointer', content: '[[Administrator]]'
|
114
128
|
end
|
115
|
-
it
|
129
|
+
it 'excludes subcard content' do
|
116
130
|
is_expected.not_to include sub1_content
|
117
131
|
is_expected.to include sub2_content
|
118
132
|
end
|
@@ -123,40 +137,45 @@ describe Card::Set::All::Notify do
|
|
123
137
|
context: @card.refresh(true),
|
124
138
|
to: Card['Joe User'].email,
|
125
139
|
follower: Card['Joe User'].name,
|
126
|
-
followed_set: @card.name+
|
140
|
+
followed_set: @card.name+'+s1+*self',
|
127
141
|
follow_option: '*always'
|
128
142
|
).text_part.body.raw_source
|
129
143
|
}
|
130
144
|
before do
|
131
|
-
Card.create_or_update! "#{name}+*self+*read",
|
132
|
-
|
145
|
+
Card.create_or_update! "#{name}+*self+*read",
|
146
|
+
type: 'Pointer', content: '[[Administrator]]'
|
147
|
+
Card.create_or_update! "#{name}+s1+*self+*read",
|
148
|
+
type: 'Pointer',content: '[[Anyone]]'
|
133
149
|
end
|
134
150
|
it 'includes subcard content' do
|
135
151
|
is_expected.to include sub1_content
|
136
152
|
end
|
137
|
-
it
|
153
|
+
it 'excludes maincard content' do
|
138
154
|
is_expected.not_to include content
|
139
155
|
is_expected.not_to be_empty
|
140
156
|
end
|
141
157
|
end
|
142
158
|
context 'for all parts' do
|
143
159
|
before do
|
144
|
-
Card.create_or_update! "#{name}+s1+*self+*read",
|
145
|
-
|
146
|
-
Card.create_or_update! "#{name}+*self+*read",
|
160
|
+
Card.create_or_update! "#{name}+s1+*self+*read",
|
161
|
+
type: 'Pointer', content: '[[Administrator]]'
|
162
|
+
Card.create_or_update! "#{name}+s2+*self+*read",
|
163
|
+
type: 'Pointer', content: '[[Administrator]]'
|
164
|
+
Card.create_or_update! "#{name}+*self+*read",
|
165
|
+
type: 'Pointer', content: '[[Administrator]]'
|
147
166
|
end
|
148
167
|
it { is_expected.not_to include content }
|
149
168
|
it { is_expected.not_to include sub1_content }
|
150
169
|
it { is_expected.not_to include sub2_content }
|
151
|
-
it
|
152
|
-
expect(Card['Joe User'].account.changes_visible? @card.acts.last)
|
170
|
+
it 'will not be send' do
|
171
|
+
expect(Card['Joe User'].account.changes_visible? @card.acts.last)
|
172
|
+
.to be_falsey
|
153
173
|
end
|
154
174
|
end
|
155
175
|
end
|
156
176
|
end
|
157
177
|
end
|
158
178
|
|
159
|
-
|
160
179
|
describe 'html format' do
|
161
180
|
include_examples 'notifications' do
|
162
181
|
let(:format) { 'email_html' }
|
@@ -169,8 +188,8 @@ describe Card::Set::All::Notify do
|
|
169
188
|
end
|
170
189
|
|
171
190
|
it 'creates well formatted text message' do
|
172
|
-
name =
|
173
|
-
content =
|
191
|
+
name = 'another card with subcards'
|
192
|
+
content = 'main content {{+s1}} {{+s2}}'
|
174
193
|
sub1_content = 'new content of subcard 1'
|
175
194
|
sub2_content = 'new content of subcard 2'
|
176
195
|
Card::Auth.as_bot do
|
@@ -235,56 +254,56 @@ Use this link to unfollow /update/Joe_User+*follow?card%5Bsubcards%5D%5Banother+
|
|
235
254
|
|
236
255
|
|
237
256
|
|
238
|
-
it
|
239
|
-
expect_user(
|
240
|
-
update
|
257
|
+
it 'sends notifications of edits' do
|
258
|
+
expect_user('Big Brother').to be_notified_of 'All Eyes On Me+*self'
|
259
|
+
update 'All Eyes On Me'
|
241
260
|
end
|
242
261
|
|
243
|
-
it
|
262
|
+
it 'does not send notification to author of change' do
|
244
263
|
Card::Auth.current_id = Card['Big Brother'].id
|
245
|
-
expect_user(
|
246
|
-
update
|
264
|
+
expect_user('Big Brother').not_to be_notified
|
265
|
+
update 'Google glass'
|
247
266
|
end
|
248
267
|
|
249
|
-
it
|
250
|
-
expect_user(
|
251
|
-
update
|
268
|
+
it 'sends only one notification per user' do
|
269
|
+
expect_user('Big Brother').to receive(:send_change_notice).exactly(1)
|
270
|
+
update 'Google glass'
|
252
271
|
end
|
253
272
|
|
254
|
-
it
|
255
|
-
expect_user(
|
256
|
-
update
|
273
|
+
it 'does not send notification of not-followed cards' do
|
274
|
+
expect_user('Big Brother').not_to be_notified
|
275
|
+
update 'No One Sees Me'
|
257
276
|
end
|
258
277
|
|
259
278
|
|
260
279
|
|
261
|
-
context
|
280
|
+
context 'when following *type sets' do
|
262
281
|
before do
|
263
282
|
Card::Auth.current_id = Card['joe admin'].id
|
264
283
|
end
|
265
284
|
|
266
|
-
it
|
267
|
-
new_card = Card.new name:
|
268
|
-
expect_user(
|
285
|
+
it 'sends notifications of new card' do
|
286
|
+
new_card = Card.new name: 'Microscope', type: 'Optic'
|
287
|
+
expect_user('Optic fan').to be_notified_of 'Optic+*type', '*always'
|
269
288
|
new_card.save!
|
270
289
|
end
|
271
290
|
|
272
|
-
it
|
273
|
-
expect_user(
|
274
|
-
update
|
291
|
+
it 'sends notification of update' do
|
292
|
+
expect_user('Optic fan').to be_notified_of 'Optic+*type', '*always'
|
293
|
+
update 'Sunglasses'
|
275
294
|
end
|
276
295
|
end
|
277
296
|
|
278
297
|
context 'when following *right sets' do
|
279
|
-
it
|
280
|
-
new_card = Card.new name:
|
281
|
-
expect_user(
|
298
|
+
it 'sends notifications of new card' do
|
299
|
+
new_card = Card.new name: 'Telescope+lens'
|
300
|
+
expect_user('Big Brother').to be_notified_of 'lens+*right', '*always'
|
282
301
|
new_card.save!
|
283
302
|
end
|
284
303
|
|
285
|
-
it
|
286
|
-
expect_user(
|
287
|
-
update
|
304
|
+
it 'sends notifications of update' do
|
305
|
+
expect_user('Big Brother').to be_notified_of 'lens+*right', '*always'
|
306
|
+
update 'Magnifier+lens'
|
288
307
|
end
|
289
308
|
end
|
290
309
|
|
@@ -302,8 +321,8 @@ Use this link to unfollow /update/Joe_User+*follow?card%5Bsubcards%5D%5Banother+
|
|
302
321
|
end
|
303
322
|
end
|
304
323
|
|
305
|
-
describe
|
306
|
-
context
|
324
|
+
describe 'notifications of fields' do
|
325
|
+
context 'when following ascendant' do
|
307
326
|
it "doesn't sends notification of arbitrary subcards" do
|
308
327
|
expect_user('Sunglasses fan').not_to be_notified
|
309
328
|
Card.create name: 'Sunglasses+about'
|
@@ -322,21 +341,21 @@ Use this link to unfollow /update/Joe_User+*follow?card%5Bsubcards%5D%5Banother+
|
|
322
341
|
end
|
323
342
|
end
|
324
343
|
|
325
|
-
context
|
326
|
-
it
|
344
|
+
context 'and follow fields rule contains *include' do
|
345
|
+
it 'sends notification of new included card' do
|
327
346
|
new_card = Card.new name: 'Sunglasses+lens'
|
328
|
-
expect_user(
|
347
|
+
expect_user('Sunglasses fan').to be_notified_of 'Sunglasses+*self'
|
329
348
|
new_card.save!
|
330
349
|
end
|
331
350
|
|
332
|
-
it
|
333
|
-
expect_user(
|
351
|
+
it 'sends notification of updated included card' do
|
352
|
+
expect_user('Sunglasses fan').to be_notified_of 'Sunglasses+*self'
|
334
353
|
update 'Sunglasses+tint'
|
335
354
|
end
|
336
355
|
|
337
356
|
it "doesn't send notification of not included card" do
|
338
357
|
new_card = Card.new name: 'Sunglasses+frame'
|
339
|
-
expect_user(
|
358
|
+
expect_user('Sunglasses fan').not_to be_notified
|
340
359
|
new_card.save!
|
341
360
|
end
|
342
361
|
end
|