card 1.16.14 → 1.16.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/db/migrate_core_cards/20150903130006_attachment_upload_cards.rb +4 -2
  4. data/lib/card/auth.rb +15 -10
  5. data/lib/card/codename.rb +25 -21
  6. data/lib/card/content.rb +100 -68
  7. data/lib/card/format.rb +158 -129
  8. data/lib/card/query.rb +15 -9
  9. data/lib/card/query/attributes.rb +41 -49
  10. data/lib/card/set.rb +15 -12
  11. data/lib/card/set_pattern.rb +4 -5
  12. data/lib/card/spec_helper.rb +54 -16
  13. data/lib/cardio.rb +43 -25
  14. data/mod/01_core/chunk/include.rb +1 -1
  15. data/mod/01_core/set/all/collection.rb +76 -73
  16. data/mod/01_core/set/all/content.rb +0 -4
  17. data/mod/01_core/set/all/fetch.rb +35 -42
  18. data/mod/01_core/set/all/name.rb +17 -7
  19. data/mod/01_core/set/all/pattern.rb +12 -11
  20. data/mod/01_core/set/all/permissions.rb +51 -42
  21. data/mod/01_core/set/all/phases.rb +2 -1
  22. data/mod/01_core/set/all/references.rb +2 -2
  23. data/mod/01_core/set/all/rules.rb +28 -35
  24. data/mod/01_core/set/all/subcards.rb +12 -12
  25. data/mod/01_core/set/all/tracked_attributes.rb +1 -1
  26. data/mod/01_core/set/all/type.rb +11 -11
  27. data/mod/01_core/set/all/utils.rb +6 -1
  28. data/mod/01_core/spec/set/all/fetch_spec.rb +6 -6
  29. data/mod/01_core/spec/set/all/permissions_spec.rb +11 -11
  30. data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +1 -1
  31. data/mod/01_history/lib/card/action.rb +52 -47
  32. data/mod/01_history/set/all/actions.rb +20 -16
  33. data/mod/01_history/set/all/history.rb +18 -13
  34. data/mod/02_basic_types/set/all/base.rb +23 -2
  35. data/mod/02_basic_types/set/type/pointer.rb +45 -36
  36. data/mod/02_basic_types/spec/set/all/base_spec.rb +40 -24
  37. data/mod/02_basic_types/spec/set/type/pointer_spec.rb +87 -0
  38. data/mod/03_machines/set/right/machine_output.rb +10 -6
  39. data/mod/04_settings/set/abstract/permission.rb +10 -5
  40. data/mod/04_settings/set/type/setting.rb +4 -1
  41. data/mod/05_email/set/all/follow.rb +39 -44
  42. data/mod/05_email/set/all/notify.rb +4 -1
  43. data/mod/05_email/set/right/followers.rb +16 -14
  44. data/mod/05_email/set/self/follow_defaults.rb +22 -19
  45. data/mod/05_standard/lib/carrier_wave/cardmount.rb +1 -0
  46. data/mod/05_standard/set/abstract/attachment.rb +85 -58
  47. data/mod/05_standard/set/all/comment.rb +35 -19
  48. data/mod/05_standard/set/all/error.rb +124 -98
  49. data/mod/05_standard/set/all/list_changes.rb +27 -22
  50. data/mod/05_standard/set/all/rich_html/editing.rb +96 -70
  51. data/mod/05_standard/set/all/rich_html/form.rb +123 -81
  52. data/mod/05_standard/set/all/rich_html/modal.rb +15 -58
  53. data/mod/05_standard/set/right/account.rb +2 -2
  54. data/mod/05_standard/set/right/email.rb +3 -2
  55. data/mod/05_standard/set/rstar/rules.rb +3 -3
  56. data/mod/05_standard/set/self/search.rb +45 -22
  57. data/mod/05_standard/set/type/cardtype.rb +13 -11
  58. data/mod/05_standard/set/type/listed_by.rb +3 -2
  59. data/mod/05_standard/set/type/set.rb +17 -13
  60. data/mod/05_standard/set/type/signup.rb +1 -2
  61. data/mod/05_standard/set/type/user.rb +1 -1
  62. data/mod/05_standard/spec/set/all/account_spec.rb +1 -1
  63. data/mod/05_standard/spec/set/all/history_spec.rb +1 -1
  64. data/mod/05_standard/spec/set/type/email_template_spec.rb +140 -134
  65. data/mod/05_standard/spec/set/type/image_spec.rb +2 -1
  66. data/mod/05_standard/spec/set/type/signup_spec.rb +2 -2
  67. data/spec/models/card/trash_spec.rb +1 -1
  68. data/spec/spec_helper.rb +0 -1
  69. metadata +2 -2
@@ -1,43 +1,66 @@
1
1
 
2
2
  format :html do
3
-
4
3
  view :title do |args|
5
4
  vars = root.search_params[:vars]
6
5
  if vars && vars[:keyword]
7
- args.merge! title: %{Search results for: <span class="search-keyword">#{ vars[:keyword] }</span>}
6
+ args.merge! title: %{Search results for: <span class="search-keyword">}\
7
+ "#{vars[:keyword]}</span>"
8
8
  end
9
9
  super args
10
10
  end
11
11
  end
12
12
 
13
-
14
13
  format :json do
15
-
16
- view :complete do |args|
17
- term = params['_keyword']
18
- if term =~ /^\+/ && main = params['main']
19
- term = main+term
20
- end
21
-
14
+ view :complete do
15
+ term = complete_term
22
16
  exact = Card.fetch term, new: {}
23
- goto_cards = Card.search goto_wql(term)
24
- goto_cards.unshift exact.name if exact.known? && !goto_cards.map{|n| n.to_name.key}.include?(exact.key)
25
17
 
26
18
  {
27
- search: true, # card.ok?( :read ),
28
- add: (exact.new_card? && exact.cardname.valid? && !exact.virtual? && exact.ok?( :create ) && exact.name),
29
- new: (exact.type_id==Card::CardtypeID &&
30
- Card.new(type_id: exact.type_id).ok?(:create) &&
31
- [exact.name, exact.cardname.url_key]
32
- ),
33
- goto: goto_cards.map { |name| [name, highlight(name, term), name.to_name.url_key] }
19
+ search: true,
20
+ add: add_item(exact),
21
+ new: new_item_of_type(exact),
22
+ goto: goto_items(term, exact)
34
23
  }
24
+ end
25
+
26
+ def add_item exact
27
+ return unless exact.new_card? &&
28
+ exact.cardname.valid? &&
29
+ !exact.virtual? &&
30
+ exact.ok?(:create)
31
+ exact.name
32
+ end
35
33
 
34
+ def new_item_of_type exact
35
+ return unless (exact.type_id == Card::CardtypeID) &&
36
+ Card.new(type_id: exact.id).ok?(:create)
37
+ [exact.name, exact.cardname.url_key]
36
38
  end
37
39
 
38
- #hacky. here for override
39
- def goto_wql(term)
40
- { complete: term, limit: 8, sort: 'name', return: 'name' }
40
+ def goto_items term, exact
41
+ goto_names = Card.search goto_wql(term), "goto items for term: #{term}"
42
+ if add_exact_to_goto_names? exact, goto_names
43
+ goto_names.unshift exact.name
44
+ end
45
+ goto_names.map do |name|
46
+ [name, highlight(name, term), name.to_name.url_key]
47
+ end
41
48
  end
42
49
 
50
+ def add_exact_to_goto_names? exact, goto_names
51
+ exact.known? && !goto_names.find { |n| n.to_name.key == exact.key }
52
+ end
53
+
54
+ def complete_term
55
+ term = params['_keyword']
56
+ if (term =~ /^\+/) && (main = params['main'])
57
+ term = main + term
58
+ end
59
+ term
60
+ end
61
+
62
+ # hacky. here for override
63
+ def goto_wql term
64
+ { complete: term, limit: 8, sort: 'name', return: 'name' }
65
+ end
43
66
  end
@@ -1,6 +1,5 @@
1
1
 
2
2
  format :html do
3
-
4
3
  view :type do |args|
5
4
  args.merge!(type_class: 'no-edit') if card.cards_of_type_exist?
6
5
  super args
@@ -8,7 +7,12 @@ format :html do
8
7
 
9
8
  view :type_formgroup do |args|
10
9
  if card.cards_of_type_exist?
11
- %{<div>Sorry, this card must remain a Cardtype so long as there are <strong>#{ card.name }</strong> cards.</div>}
10
+ %{
11
+ <div>
12
+ Sorry, this card must remain a Cardtype so long as there are
13
+ <strong>#{card.name}</strong> cards.
14
+ </div>
15
+ }
12
16
  else
13
17
  super args
14
18
  end
@@ -33,36 +37,34 @@ format :html do
33
37
  if args[:params]
34
38
  context = ((@parent && @parent.card) || card).name
35
39
  Rack::Utils.parse_nested_query(args[:params]).each do |key, value|
36
- value = value.to_name.to_absolute(context) if value
37
- key = key.to_name.to_absolute(context)
38
- path_args[key] = value
40
+ value = value.to_name.to_absolute(context) if value
41
+ key = key.to_name.to_absolute(context)
42
+ path_args[key] = value
39
43
  end
40
44
  end
41
45
  path_args[:action] = 'new'
42
46
  page_path card.cardname, path_args
43
47
  end
44
-
45
48
  end
46
49
 
47
-
48
50
  include Basic
49
51
 
50
-
51
52
  def follow_label
52
53
  default_follow_set_card.follow_label
53
54
  end
54
55
 
55
- def followed_by? user_id = nil
56
+ def followed_by? user_id=nil
56
57
  default_follow_set_card.all_members_followed_by? user_id
57
58
  end
58
59
 
59
60
  def default_follow_set_card
61
+ # FIXME: use codename
60
62
  Card.fetch("#{name}+*type")
61
63
  end
62
64
 
63
-
64
65
  def cards_of_type_exist?
65
- !new_card? and Auth.as_bot { Card.count_by_wql type_id: id } > 0
66
+ # FIXME: faster test than counting all of type?
67
+ !new_card? && Auth.as_bot { Card.count_by_wql type_id: id } > 0
66
68
  end
67
69
 
68
70
  event :check_for_cards_of_type, after: :validate_delete do
@@ -59,8 +59,9 @@ end
59
59
 
60
60
  def listed_by
61
61
  Card.search(
62
- type: 'list', right: trunk.type_name,
63
- left: { type: cardname.tag }, refer_to: cardname.trunk, return: :name
62
+ { type: 'list', right: trunk.type_name,
63
+ left: { type: cardname.tag }, refer_to: cardname.trunk, return: :name
64
+ }, 'listed_by' # better wql comment would be...better
64
65
  )
65
66
  end
66
67
 
@@ -1,14 +1,14 @@
1
1
 
2
2
  format :html do
3
-
4
3
  view :core do |args|
5
4
  _render args[:rule_view], args
6
5
  end
6
+
7
7
  def default_core_args args
8
8
  args[:rule_view] ||= :common_rules
9
- args[:optional_set_label] ||= :show
9
+ args[:optional_set_label] ||= :show
10
+ args[:optional_set_navbar] ||= :hide
10
11
  args[:optional_rule_navbar] ||= :show
11
- args[:optional_set_navbar] ||= :hide
12
12
  end
13
13
 
14
14
  def with_label_and_navbars args
@@ -24,16 +24,20 @@ format :html do
24
24
 
25
25
  view :all_rules do |args|
26
26
  with_label_and_navbars args.merge(selected_view: :all_rules) do
27
- rules_table (card.visible_setting_codenames.sort & card.visible_setting_codenames), args
27
+ rules_table card.visible_setting_codenames.sort, args
28
28
  end
29
29
  end
30
30
 
31
31
  view :grouped_rules do |args|
32
32
  with_label_and_navbars args.merge(selected_view: :grouped_rules) do
33
- content_tag(:div, class: 'panel-group', id: 'accordion', role: 'tablist','aria-multiselectable'=>'true') do
34
- Card::Setting.groups.keys.map do |group_key|
35
- _optional_render(group_key, args, :show)
36
- end * "\n"
33
+ content_tag(:div, class: 'panel-group',
34
+ id: 'accordion',
35
+ role: 'tablist',
36
+ 'aria-multiselectable' => 'true'
37
+ ) do
38
+ Card::Setting.groups.keys.map do |group_key|
39
+ _optional_render(group_key, args, :show)
40
+ end * "\n"
37
41
  end
38
42
  end
39
43
  end
@@ -201,20 +205,20 @@ def followed_by? user_id = nil
201
205
  all_members_followed_by? user_id
202
206
  end
203
207
 
204
-
205
208
  def default_follow_set_card
206
209
  self
207
210
  end
208
211
 
209
212
  def inheritable?
210
213
  return true if junction_only?
211
- cardname.trunk_name.junction? and cardname.tag_name.key == Card::SelfSet.pattern.key
214
+ cardname.trunk_name.junction? &&
215
+ cardname.tag_name.key == Card::SelfSet.pattern.key
212
216
  end
213
217
 
214
218
  def subclass_for_set
215
- set_class_key = tag.codename
216
- Card.set_patterns.find do |sub|
217
- cardname.tag_name.key == sub.pattern.key
219
+ current_set_pattern_code = tag.codename
220
+ Card.set_patterns.detect do |set|
221
+ current_set_pattern_code == set.pattern_code
218
222
  end
219
223
  end
220
224
 
@@ -4,8 +4,7 @@ format :html do
4
4
  super args
5
5
  args.merge!(
6
6
  optional_help: :show, # , optional_menu: :never
7
- buttons: button_tag(' Submit',
8
- disable_with: 'Submitting', situation: 'primary'),
7
+ buttons: submit_button,
9
8
  account: card.fetch(trait: :account, new: {}),
10
9
  title: 'Sign up',
11
10
  hidden: {
@@ -45,7 +45,7 @@ format :html do
45
45
  end
46
46
 
47
47
  def setup_button
48
- button_tag 'Set up', disable_with: 'Setting up', situation: 'primary'
48
+ submit_button text: 'Set up', disable_with: 'Setting up'
49
49
  end
50
50
  end
51
51
 
@@ -126,7 +126,7 @@ describe Card::Set::All::Account do
126
126
 
127
127
  it "9 more should apply to Joe Admin" do
128
128
  # includes lots of account rules...
129
- Card::Auth.as(:joe_admin) do
129
+ Card::Auth.as('joe_admin') do
130
130
  ids = Card::Auth.as_card.read_rules
131
131
  expect(ids.length).to eq(@read_rules.size + 9)
132
132
  end
@@ -93,7 +93,7 @@ describe Card::Set::All::History do
93
93
  end
94
94
 
95
95
  it "doesn't create act and actions if subcard fails" do
96
- Card::Auth.as(:joe_user) do
96
+ Card::Auth.as('joe_user') do
97
97
  act_count = Card::Act.count
98
98
  action_count = Card::Action.count
99
99
  Card.create name: "crete fail", subcards: {'*all+*create'=>''}
@@ -3,7 +3,7 @@ require 'card/mailer'
3
3
 
4
4
  describe Card::Set::Type::EmailTemplate do
5
5
  let(:email_name) { 'a mail template' }
6
- let(:email) {Card.fetch(email_name)}
6
+ let(:email) { Card.fetch(email_name) }
7
7
 
8
8
  def mailconfig args={}
9
9
  Card[email_name].email_config(args)
@@ -19,66 +19,65 @@ describe Card::Set::Type::EmailTemplate do
19
19
 
20
20
  before do
21
21
  Card::Auth.current_id = Card::WagnBotID
22
- chunk_test = "Url(wagn.org) Link([[http://wagn.org|Wagn]]) Inclusion({{B|name}}) Card link([[A]])"
22
+ chunk_test = 'Url(wagn.org) Link([[http://wagn.org|Wagn]])'\
23
+ ' Inclusion({{B|name}}) Card link([[A]])'
23
24
  Card.create! name: email_name, type: :email_template, subcards: {
24
- "+*to" => "joe@user.com",
25
- "+*from" => "from@user.com",
26
- "+*subject" => "*subject #{chunk_test}",
27
- "+*html_message" => "*html message #{chunk_test}",
28
- "+*text_message" => "*text message #{chunk_test}"
25
+ '+*to' => 'joe@user.com',
26
+ '+*from' => 'from@user.com',
27
+ '+*subject' => "*subject #{chunk_test}",
28
+ '+*html_message' => "*html message #{chunk_test}",
29
+ '+*text_message' => "*text message #{chunk_test}"
29
30
  }
30
31
  end
31
32
 
32
- describe "mail view" do
33
+ describe 'mail view' do
33
34
  let(:content_type) do
34
- card = Card.create!(name: 'content type test', type: :email_template, subcards: @fields)
35
+ card = Card.create!(name: 'content type test', type: :email_template,
36
+ subcards: @fields)
35
37
  email = card.format.render_mail
36
38
  email[:content_type].value
37
39
  end
38
40
 
39
41
  it 'renders text email if text message given' do
40
- @fields = { "+*text_message" => "text" }
42
+ @fields = { '+*text_message' => 'text' }
41
43
  expect(content_type).to include 'text/plain'
42
44
  end
43
45
 
44
46
  it 'renders html email if html message given' do
45
- @fields = { "+*html_message" => "text" }
47
+ @fields = { '+*html_message' => 'text' }
46
48
  expect(content_type).to include 'text/html'
47
49
  end
48
50
 
49
51
  it 'renders multipart email if text and html given' do
50
- @fields = {'+*text_message'=>'text', '+*html_message'=>'text'}
52
+ @fields = { '+*text_message' => 'text', '+*html_message' => 'text' }
51
53
  expect(content_type).to include 'multipart/alternative'
52
54
  end
53
-
54
55
  end
55
56
 
56
-
57
- describe "#email_config" do
58
-
57
+ describe '#email_config' do
59
58
  describe 'address fields' do
60
59
  it 'uses *from field' do
61
- expect( mailconfig[:from] ).to eq 'from@user.com'
60
+ expect(mailconfig[:from]).to eq 'from@user.com'
62
61
  end
63
62
 
64
63
  it 'uses *to field' do
65
- expect( mailconfig[:to] ).to eq 'joe@user.com'
64
+ expect(mailconfig[:to]).to eq 'joe@user.com'
66
65
  end
67
66
 
68
67
  it 'handles pointer values' do
69
- create_field '*cc', content: "[[joe@user.com]]", type: 'Pointer'
70
- expect( mailconfig[:cc] ).to eq 'joe@user.com'
68
+ create_field '*cc', content: '[[joe@user.com]]', type: 'Pointer'
69
+ expect(mailconfig[:cc]).to eq 'joe@user.com'
71
70
  end
72
71
 
73
-
74
- #it 'handles email syntax in pointer values' do
75
- # create_field '*cc', content: "[[Joe User <joe@user.com>]]", type: 'Pointer'
72
+ # it 'handles email syntax in pointer values' do
73
+ # create_field '*cc', content: "[[Joe User <joe@user.com>]]",
74
+ # type: 'Pointer'
76
75
  # expect( mailconfig[:cc] ).to eq 'Joe User <joe@user.com>'
77
- #end
76
+ # end
78
77
 
79
78
  it 'handles link to email card' do
80
- create_field '*cc', content: "[[Joe User+*email]]", type: 'Pointer'
81
- expect( mailconfig[:cc] ).to eq 'joe@user.com'
79
+ create_field '*cc', content: '[[Joe User+*email]]', type: 'Pointer'
80
+ expect(mailconfig[:cc]).to eq 'joe@user.com'
82
81
  end
83
82
 
84
83
  # it 'handles link with valid email address' do
@@ -87,120 +86,127 @@ describe Card::Set::Type::EmailTemplate do
87
86
  # end
88
87
 
89
88
  it 'handles search card' do
90
- create_field '*bcc', content: '{"name":"Joe Admin","append":"*email"}', type: 'Search'
91
- expect( mailconfig[:bcc] ).to eq 'joe@admin.com'
89
+ create_field '*bcc', content: '{"name":"Joe Admin","append":"*email"}',
90
+ type: 'Search'
91
+ expect(mailconfig[:bcc]).to eq 'joe@admin.com'
92
92
  end
93
-
94
- # it 'handles invalid email address' do #TODO not obvious how to deal with that.
95
- # we can't decided whether a email address like [[_left]] is valid; depends on the context
96
- # Card.fetch("a mail template+*to").update_attributes(content: "invalid mail address")
93
+ # TODO: not obvious how to deal with that.
94
+ # it 'handles invalid email address' do
95
+ # we can't decided whether a email address like [[_left]] is valid;
96
+ # depends on the context
97
+ # Card.fetch("a mail template+*to").
98
+ # update_attributes(content: "invalid mail address")
97
99
  # end
98
100
  end
99
101
 
102
+ describe 'subject' do
103
+ subject { mailconfig[:subject] }
100
104
 
101
- describe 'subject' do
102
- subject { mailconfig[:subject] }
103
-
104
- it 'uses *subject field' do
105
+ it 'uses *subject field' do
105
106
  is_expected.to include '*subject'
106
- end
107
- it 'does not render url' do
108
- is_expected.to include 'Url(wagn.org)'
109
- end
110
- it 'does not render link' do
111
- is_expected.to include 'Link([[http://wagn.org|Wagn]])'
112
- end
113
- it 'renders inclusion' do
114
- is_expected.to include 'Inclusion(B)'
115
- end
116
- end
117
-
118
- describe 'text message' do
119
- subject { mailconfig[:text_message] }
120
-
121
- it 'uses *text_message field' do
122
- is_expected.to include '*text message'
123
- end
124
- it 'does not render url' do
125
- is_expected.to include 'Url(wagn.org)'
126
- end
127
- it 'renders link' do
128
- is_expected.to include 'Link(Wagn[http://wagn.org])'
129
- end
130
- it 'renders inclusion' do
131
- is_expected.to include 'Inclusion(B)'
132
- end
133
-
134
- end
135
-
136
- describe 'html message' do
137
- subject { mailconfig[:html_message] }
138
-
139
- it 'uses *html_message field' do
140
- is_expected.to include '*html message'
141
- end
142
- it 'renders url' do
143
- is_expected.to include 'Url(<a target="_blank" class="external-link" href="http://wagn.org">wagn.org</a>)'
144
- end
145
- it 'renders link' do
146
- is_expected.to include 'Link(<a target="_blank" class="external-link" href="http://wagn.org">Wagn</a>)'
147
- end
148
- it 'renders inclusion' do
149
- is_expected.to include 'Inclusion(B)'
150
- end
151
- it "renders absolute urls" do
152
- Card::Env[:protocol] = 'http://'
153
- Card::Env[:host] = 'www.fake.com'
154
- is_expected.to include 'Card link(<a class="known-card" href="http://www.fake.com/A">A</a>)'
155
- end
156
- end
157
-
158
-
159
- context 'with context card' do
160
- let(:context_card) do
161
- Card.create(
162
- name: "Banana",
163
- content: "data content [[A]]",
164
- subcards: {
165
- '+email' => {content: 'gary@gary.com'},
166
- '+subject' => {type: 'Pointer', content: '[[default subject]]'},
167
- '+attachment' => {type: 'File', content: "notreally.txt" }
168
- }
169
- )
170
- end
171
- subject { mailconfig( context: context_card ) }
172
-
173
- it 'handles contextual name in address search' do
174
- update_field '*from', content: '{"left":"_self", "right":"email"}', type: 'Search'
175
- expect(subject[:from]).to eq "gary@gary.com"
176
- end
177
-
178
- it 'handles contextual names and structure rules in subject' do
179
- Card.create! name: 'default subject', content: 'a very nutty thang', type: 'Phrase'
180
- Card.create! name: "subject search+*right+*structure", content: %{{"referred_to_by":"_left+subject"}}, type: 'Search'
181
- update_field '*subject', content: "{{+subject search|core;item:core}}"
182
- expect(subject[:subject]).to eq("a very nutty thang")
183
- end
184
-
185
- it 'handles _self in html message' do
186
- update_field '*html message', content: "Triggered by {{_self|name}}"
187
- expect(subject[:html_message]).to include("Triggered by Banana")
188
- end
189
-
190
- it 'handles _left in html message' do
191
- update_field '*html_message', content: "Nobody expects {{_left+surprise|core}}"
192
- Card.create name: 'Banana+surprise', content: "the Spanish Inquisition"
193
- c = Card.create name: "Banana+emailtest", content: "data content"
194
- expect( mailconfig( context: c )[:html_message] ).to include 'Nobody expects the Spanish Inquisition'
195
-
196
- end
197
-
198
- it 'handles contextual name for attachments' do
199
- create_field '*attach', type: "Pointer", content: "[[_self+attachment]]"
200
- expect(subject[:attach]).to eq ['Banana+attachment'.to_name]
201
- end
202
- end
107
+ end
108
+ it 'does not render url' do
109
+ is_expected.to include 'Url(wagn.org)'
110
+ end
111
+ it 'does not render link' do
112
+ is_expected.to include 'Link([[http://wagn.org|Wagn]])'
113
+ end
114
+ it 'renders inclusion' do
115
+ is_expected.to include 'Inclusion(B)'
116
+ end
117
+ end
203
118
 
204
- end
119
+ describe 'text message' do
120
+ subject { mailconfig[:text_message] }
121
+
122
+ it 'uses *text_message field' do
123
+ is_expected.to include '*text message'
124
+ end
125
+ it 'does not render url' do
126
+ is_expected.to include 'Url(wagn.org)'
127
+ end
128
+ it 'renders link' do
129
+ is_expected.to include 'Link(Wagn[http://wagn.org])'
130
+ end
131
+ it 'renders inclusion' do
132
+ is_expected.to include 'Inclusion(B)'
133
+ end
134
+ end
135
+
136
+ describe 'html message' do
137
+ subject { mailconfig[:html_message] }
205
138
 
139
+ it 'uses *html_message field' do
140
+ is_expected.to include '*html message'
141
+ end
142
+ it 'renders url' do
143
+ is_expected.to include 'Url(<a target="_blank" class="external-link" '\
144
+ 'href="http://wagn.org">wagn.org</a>)'
145
+ end
146
+ it 'renders link' do
147
+ is_expected.to include 'Link(<a target="_blank" class="external-link" '\
148
+ 'href="http://wagn.org">Wagn</a>)'
149
+ end
150
+ it 'renders inclusion' do
151
+ is_expected.to include 'Inclusion(B)'
152
+ end
153
+ it 'renders absolute urls' do
154
+ Card::Env[:protocol] = 'http://'
155
+ Card::Env[:host] = 'www.fake.com'
156
+ is_expected.to include 'Card link(<a class="known-card" '\
157
+ 'href="http://www.fake.com/A">A</a>)'
158
+ end
159
+ end
160
+
161
+ context 'with context card' do
162
+ let(:context_card) do
163
+ file = File.new(File.join FIXTURES_PATH, 'mao2.jpg')
164
+ Card.create(
165
+ name: 'Banana',
166
+ content: 'data content [[A]]',
167
+ subcards: {
168
+ '+email' => { content: 'gary@gary.com' },
169
+ '+subject' => { type: 'Pointer', content: '[[default subject]]' },
170
+ '+attachment' => { type: 'File', file: file }
171
+ }
172
+ )
173
+ end
174
+ subject { mailconfig(context: context_card) }
175
+
176
+ it 'handles contextual name in address search' do
177
+ update_field '*from', content: '{"left":"_self", "right":"email"}',
178
+ type: 'Search'
179
+ expect(subject[:from]).to eq 'gary@gary.com'
180
+ end
181
+
182
+ it 'handles contextual names and structure rules in subject' do
183
+ Card.create! name: 'default subject', content: 'a very nutty thang',
184
+ type: 'Phrase'
185
+ Card.create! name: 'subject search+*right+*structure',
186
+ content: %{{"referred_to_by":"_left+subject"}},
187
+ type: 'Search'
188
+ update_field '*subject', content: '{{+subject search|core;item:core}}'
189
+ expect(subject[:subject]).to eq('a very nutty thang')
190
+ end
191
+
192
+ it 'handles _self in html message' do
193
+ update_field '*html message', content: 'Triggered by {{_self|name}}'
194
+ expect(subject[:html_message]).to include('Triggered by Banana')
195
+ end
196
+
197
+ it 'handles _left in html message' do
198
+ update_field '*html_message',
199
+ content: 'Nobody expects {{_left+surprise|core}}'
200
+ Card.create name: 'Banana+surprise', content: 'the Spanish Inquisition'
201
+ c = Card.create name: 'Banana+emailtest', content: 'data content'
202
+ expected = mailconfig(context: c)[:html_message]
203
+ expect(expected).to include 'Nobody expects the Spanish Inquisition'
204
+ end
205
+
206
+ it 'handles contextual name for attachments' do
207
+ create_field '*attach', type: 'Pointer', content: '[[_self+attachment]]'
208
+ expect(subject[:attach]).to eq ['Banana+attachment'.to_name]
209
+ end
210
+ end
211
+ end
206
212
  end