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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +1 -1
  4. data/db/migrate_core_cards/20130823192433_add_style_cards.rb +39 -24
  5. data/db/migrate_core_cards/20140629222005_add_email_cards.rb +6 -11
  6. data/db/migrate_core_cards/20151120180631_add_token_expiration.rb +7 -0
  7. data/db/seed/new/card_actions.yml +396 -388
  8. data/db/seed/new/card_acts.yml +1 -595
  9. data/db/seed/new/card_changes.yml +8154 -23619
  10. data/db/seed/new/card_references.yml +1009 -988
  11. data/db/seed/new/cards.yml +1445 -1423
  12. data/db/seed/test/fixtures/card_actions.yml +1375 -1399
  13. data/db/seed/test/fixtures/card_acts.yml +445 -1063
  14. data/db/seed/test/fixtures/card_changes.yml +11440 -26881
  15. data/db/seed/test/fixtures/card_references.yml +1523 -1502
  16. data/db/seed/test/fixtures/cards.yml +2736 -2715
  17. data/db/seed/test/seed.rb +7 -10
  18. data/db/version_core_cards.txt +1 -1
  19. data/lib/card/auth.rb +65 -19
  20. data/lib/card/cache.rb +18 -18
  21. data/lib/card/env.rb +10 -10
  22. data/lib/card/format.rb +41 -30
  23. data/lib/card/location.rb +3 -5
  24. data/lib/card/subcards.rb +0 -3
  25. data/lib/card/success.rb +14 -11
  26. data/mod/01_core/set/all/subcards.rb +4 -2
  27. data/mod/01_core/set/all/trash.rb +4 -1
  28. data/mod/02_basic_types/set/type/pointer.rb +5 -2
  29. data/mod/05_email/set/all/notify.rb +85 -73
  30. data/mod/05_email/spec/set/all/notify_spec.rb +74 -55
  31. data/mod/05_standard/set/all/comment.rb +18 -12
  32. data/mod/05_standard/set/all/error.rb +5 -1
  33. data/mod/05_standard/set/right/account.rb +50 -73
  34. data/mod/05_standard/set/right/token.rb +49 -2
  35. data/mod/05_standard/set/self/signin.rb +14 -12
  36. data/mod/05_standard/set/type/signup.rb +17 -21
  37. data/mod/05_standard/spec/set/all/account_spec.rb +1 -1
  38. data/mod/05_standard/spec/set/right/account_spec.rb +76 -52
  39. data/mod/05_standard/spec/set/right/password_spec.rb +10 -11
  40. data/mod/05_standard/spec/set/right/token_spec.rb +19 -1
  41. data/mod/05_standard/spec/set/type/signup_spec.rb +3 -4
  42. data/spec/lib/card/auth_spec.rb +46 -5
  43. 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?) && !subcards.present?
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 = %w{ default style layout create read update delete }
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
- self.add_item Env.params['add_item'] if Env.params['add_item']
4
- self.drop_item Env.params['drop_item'] if Env.params['drop_item']
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
- if !@visited.include? card.key
12
- @visited.add card.key
13
- card.all_direct_follower_ids_with_reason do |user_id, reason|
14
- notify Card.fetch(user_id), of: reason
15
- end
16
- if card.left and !@visited.include?(card.left.name) and follow_field_rule = card.left.rule_card(:follow_fields)
17
-
18
- follow_field_rule.item_names(context: card.left.cardname).each do |item|
19
- if @visited.include? item.to_name.key
20
- add_affected_card card.left
21
- break
22
- elsif item.to_name.key == Card[:includes].key
23
- includee_set = Card.search(included_by: card.left.name).map(&:key)
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 # "follower" is a card object, "followed" a card name
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 && Card::Auth.current_id != WagnBotID && followable?
68
+ !silent_change? && !supercard && current_act &&
69
+ Card::Auth.current_id != WagnBotID && followable?
67
70
  end
68
71
 
69
- event :notify_followers_after_save, after: :subsequent, on: :save, when: proc{ |ca| ca.notable_change? } do
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 subsequent phase
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 ||= FollowerStash.new
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, after: :extend, on: :delete,
81
- when: proc{ |ca| ca.notable_change? } do
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
- begin
87
- @current_act.reload
88
- @follower_stash ||= FollowerStash.new
89
- @current_act.actions.each do |a|
90
- @follower_stash.add_affected_card a.card if a.card
91
- end
92
- @follower_stash.each_follower_with_reason do |follower, reason|
93
- if follower.account and follower != @current_act.actor
94
- follower.account.send_change_notice @current_act, reason[:set_card].name, reason[:option]
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 = case action.action_type
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).render_subedit_notice(action: action)
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 = (action.new_values[:name] && action.old_values[:name]) || card.name
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] && (set_card = Card.fetch(args[:followed_set])) &&
145
- args[:follow_option] && (option_card = Card.fetch(args[:follow_option]))
146
- option_card.description set_card
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])) && args[:follow_option] && args[:follower]
158
- rule_name = set_card.follow_rule_name args[:follower]
159
- target_name = "#{args[:follower]}+#{Card[:follow].name}"
160
- update_path = page_path target_name, action: :update, card: {subcards: {rule_name=>Card[:never].name}}
161
- card_url update_path # absolutize path
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 = case action.action_type
169
- when :update then 'new '
170
- when :delete then 'deleted '
171
- else ''
172
- end
173
- item_title += "#{field}: "
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
- wrap_list_item "#{item_title}#{item_value}"
197
+ wrap_list_item "#{item_title}#{item_value}"
183
198
  end
184
199
 
185
200
  def get_act args
186
- @notification_act ||= args[:act] || (args[:act_id] and Act.find(args[:act_id])) || card.acts.last
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] and Action.fetch(args[:action_id])) || card.last_action
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 { @card.update_attributes!(name: 'bnn card', type: :pointer, content: 'changed content') }
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!(name: 'bnn card', type: :pointer, content: 'changed content')
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!(name: 'bnn card', type: :pointer, content: 'changed content')
40
- @card.format(format: format).render_list_of_changes(action_id: action_id)
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 { @card.update_attributes!(name: changed_name, content: changed_content) }
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 = "another card with subcards"
86
- content = "main content {{+s1}} {{+s2}}"
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", type: 'Pointer', content: '[[Administrator]]'
126
+ Card.create_or_update! "#{name}+s1+*self+*read",
127
+ type: 'Pointer', content: '[[Administrator]]'
114
128
  end
115
- it "excludes subcard content" do
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+"+s1+*self",
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",type: 'Pointer',content: '[[Administrator]]'
132
- Card.create_or_update! "#{name}+s1+*self+*read",type: 'Pointer',content: '[[Anyone]]'
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 "excludes maincard content" do
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",type: 'Pointer',content: '[[Administrator]]'
145
- Card.create_or_update! "#{name}+s2+*self+*read",type: 'Pointer',content: '[[Administrator]]'
146
- Card.create_or_update! "#{name}+*self+*read",type: 'Pointer',content: '[[Administrator]]'
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 "will not be send" do
152
- expect(Card['Joe User'].account.changes_visible? @card.acts.last).to be_falsey
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 = "another card with subcards"
173
- content = "main content {{+s1}} {{+s2}}"
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 "sends notifications of edits" do
239
- expect_user("Big Brother").to be_notified_of "All Eyes On Me+*self"
240
- update "All Eyes On Me"
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 "does not send notification to author of change" do
262
+ it 'does not send notification to author of change' do
244
263
  Card::Auth.current_id = Card['Big Brother'].id
245
- expect_user("Big Brother").not_to be_notified
246
- update "Google glass"
264
+ expect_user('Big Brother').not_to be_notified
265
+ update 'Google glass'
247
266
  end
248
267
 
249
- it "sends only one notification per user" do
250
- expect_user("Big Brother").to receive(:send_change_notice).exactly(1)
251
- update "Google glass"
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 "does not send notification of not-followed cards" do
255
- expect_user("Big Brother").not_to be_notified
256
- update "No One Sees Me"
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 "when following *type sets" do
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 "sends notifications of new card" do
267
- new_card = Card.new name: "Microscope", type: "Optic"
268
- expect_user("Optic fan").to be_notified_of "Optic+*type", "*always"
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 "sends notification of update" do
273
- expect_user("Optic fan").to be_notified_of "Optic+*type", '*always'
274
- update "Sunglasses"
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 "sends notifications of new card" do
280
- new_card = Card.new name: "Telescope+lens"
281
- expect_user("Big Brother").to be_notified_of "lens+*right", '*always'
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 "sends notifications of update" do
286
- expect_user("Big Brother").to be_notified_of "lens+*right", '*always'
287
- update "Magnifier+lens"
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 "notifications of fields" do
306
- context "when following ascendant" do
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 "and follow fields rule contains *include" do
326
- it "sends notification of new included card" do
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("Sunglasses fan").to be_notified_of "Sunglasses+*self"
347
+ expect_user('Sunglasses fan').to be_notified_of 'Sunglasses+*self'
329
348
  new_card.save!
330
349
  end
331
350
 
332
- it "sends notification of updated included card" do
333
- expect_user("Sunglasses fan").to be_notified_of "Sunglasses+*self"
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("Sunglasses fan").not_to be_notified
358
+ expect_user('Sunglasses fan').not_to be_notified
340
359
  new_card.save!
341
360
  end
342
361
  end