wagn 1.18.6 → 1.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +2 -2
  3. data/bin/wagn +3 -3
  4. data/features/notifications.feature +1 -0
  5. data/features/rules.feature +2 -0
  6. data/features/step_definitions/email_steps.rb +10 -2
  7. data/features/step_definitions/history_steps.rb +1 -1
  8. data/features/step_definitions/wagn_steps.rb +72 -48
  9. data/features/step_definitions/web_steps.rb +12 -12
  10. data/features/step_definitions/window_steps.rb +3 -3
  11. data/features/structure.feature +1 -0
  12. data/features/support/delayed_job.rb +18 -0
  13. data/features/support/env.rb +43 -24
  14. data/features/support/paths.rb +4 -4
  15. data/features/support/scopes.rb +6 -6
  16. data/features/support/wagn_env.rb +2 -2
  17. data/features/table_of_contents.feature +1 -0
  18. data/features/update_includers.feature +2 -4
  19. data/lib/decko/engine.rb +29 -28
  20. data/lib/wagn.rb +1 -1
  21. data/lib/wagn/all.rb +1 -1
  22. data/lib/wagn/application.rb +9 -9
  23. data/lib/wagn/cli.rb +5 -5
  24. data/lib/wagn/commands.rb +48 -48
  25. data/lib/wagn/commands/application.rb +4 -4
  26. data/lib/wagn/config/environments/cucumber.rb +2 -0
  27. data/lib/wagn/config/environments/development.rb +2 -2
  28. data/lib/wagn/config/environments/production.rb +2 -2
  29. data/lib/wagn/config/environments/test.rb +12 -3
  30. data/lib/wagn/config/initializers/secret_token.rb +2 -2
  31. data/lib/wagn/generators/wagn/templates/Gemfile +38 -51
  32. data/lib/wagn/generators/wagn/templates/bin/spring +6 -6
  33. data/lib/wagn/generators/wagn/templates/config/application.rb +12 -1
  34. data/lib/wagn/generators/wagn/templates/spec/javascripts/support/deck_jasmine.yml +2 -2
  35. data/lib/wagn/generators/wagn/templates/spec/javascripts/support/wagn_jasmine.yml +15 -10
  36. data/lib/wagn/generators/wagn/templates/spec/spec_helper.rb +1 -1
  37. data/lib/wagn/generators/wagn/wagn_generator.rb +87 -87
  38. data/lib/wagn/generators/wagn/wagn_generator/interactive.rb +28 -28
  39. data/lib/wagn/mods_spec_helper.rb +9 -9
  40. data/lib/wagn/parser.rb +27 -27
  41. data/lib/wagn/response.rb +106 -0
  42. data/lib/wagn/script_wagn_loader.rb +4 -4
  43. data/lib/wagn/simplecov_helper.rb +19 -19
  44. data/lib/wagn/tasks/cucumber.rake +19 -19
  45. data/lib/wagn/tasks/db.rake +8 -8
  46. data/lib/wagn/tasks/test.rake +25 -25
  47. data/lib/wagn/tasks/wagn.rake +107 -110
  48. data/rails/application-routes.rb +2 -2
  49. data/rails/controllers/card_controller.rb +37 -196
  50. data/rails/engine-routes.rb +29 -29
  51. data/script/autospec +3 -3
  52. data/script/rails +3 -3
  53. data/script/test_filter +2 -2
  54. data/script/wagn +3 -3
  55. data/spec/controllers/card_controller_spec.rb +194 -170
  56. data/spec/controllers/location_spec.rb +10 -10
  57. data/spec/javascripts/support/jasmine.yml.erb +4 -4
  58. data/spec/javascripts/support/jasmine_config.rb +4 -4
  59. data/spec/javascripts/support/jasmine_runner.rb +5 -5
  60. data/test/performance/card_create_test.rb +5 -5
  61. data/test/performance/fetch_test.rb +3 -3
  62. data/test/performance/homepage_test.rb +3 -3
  63. data/test/performance/render_test.rb +3 -3
  64. data/test/test_helper.rb +14 -14
  65. data/wagn.gemspec +16 -16
  66. metadata +7 -5
@@ -1,6 +1,6 @@
1
1
  Wagn.application.routes.draw do
2
2
  if !Rails.env.production? && Object.const_defined?(:JasmineRails)
3
- mount Object.const_get(:JasmineRails).const_get(:Engine) => '/specs'
3
+ mount Object.const_get(:JasmineRails).const_get(:Engine) => "/specs"
4
4
  end
5
- mount Decko::Engine => '/'
5
+ mount Decko::Engine => "/"
6
6
  end
@@ -1,14 +1,17 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- require_dependency 'card'
3
+ require_dependency "card"
4
4
 
5
- require_dependency 'wagn/exceptions'
6
- require_dependency 'card/mailer' # otherwise Net::SMTPError rescues can cause
5
+ require_dependency "wagn/exceptions"
6
+ require_dependency "wagn/response"
7
+ require_dependency "card/mailer" # otherwise Net::SMTPError rescues can cause
7
8
  # problems when error raised comes before Card::Mailer is mentioned
8
9
 
10
+ # Wagn's only controller.
9
11
  class CardController < ActionController::Base
10
- include Card::Location
12
+ include Card::Env::Location
11
13
  include Recaptcha::Verify
14
+ include Wagn::Response
12
15
 
13
16
  layout nil
14
17
  attr_reader :card
@@ -32,13 +35,11 @@ class CardController < ActionController::Base
32
35
  handle { card.delete }
33
36
  end
34
37
 
35
- # DEPRECATED
38
+ # @deprecated
36
39
  def asset
37
- Rails.logger.info 'Routing assets through Card. Recommend symlink from ' \
40
+ Rails.logger.info "Routing assets through Card. Recommend symlink from " \
38
41
  'Deck to Card gem using "rake wagn:update_assets_symlink"'
39
- asset_path = Decko::Engine.paths['gem-assets'].existent.first
40
- filename = [params[:filename], params[:format]].join('.')
41
- send_asset asset_path, filename, x_sendfile: true
42
+ send_deprecated_asset
42
43
  end
43
44
 
44
45
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -52,41 +53,28 @@ class CardController < ActionController::Base
52
53
  before_filter :authenticate, except: [:asset]
53
54
  before_filter :load_id, only: [:read]
54
55
  before_filter :load_card, except: [:asset]
55
- before_filter :refresh_card, only: [:create, :update, :delete, :rollback]
56
+ before_filter :refresh_card, only: [:create, :update, :delete]
56
57
 
57
58
  def setup
58
59
  request.format = :html unless params[:format] # is this used??
60
+ Card::Mod::Loader.refresh_script_and_style if Rails.env.development?
59
61
  Card::Cache.renew
60
62
  Card::Env.reset controller: self
61
63
  end
62
64
 
63
65
  def authenticate
64
- if params[:token]
65
- ok = Card::Auth.set_current_from_token params[:token], params[:current]
66
- raise Card::Oops, 'token authentication failed' unless ok
67
- # arguably should be PermissionDenied; that requires a card object,
68
- # and that's not loaded yet.
69
- else
70
- Card::Auth.set_current_from_session
71
- end
66
+ Card::Auth.set_current params[:token], params[:current]
72
67
  end
73
68
 
74
69
  def load_id
75
- params[:id] =
76
- case params[:id]
77
- when '*previous' then return card_redirect(Card::Env.previous_location)
78
- when nil then determine_id
79
- else validate_id_encoding params[:id]
80
- end
70
+ params[:id] = interpret_id params[:id]
81
71
  end
82
72
 
83
73
  def load_card
84
- @card = new_or_fetch_card
85
- raise Card::NotFound unless @card
86
-
74
+ @card = Card.deep_fetch params
75
+ raise Card::Error::NotFound unless @card
87
76
  @card.select_action_by_params params #
88
- Card::Env[:main_name] = params[:main] || (card && card.name) || ''
89
-
77
+ Card::Env[:main_name] = params[:main] || (card && card.name) || ""
90
78
  card.errors.any? ? render_errors : true
91
79
  end
92
80
 
@@ -96,77 +84,6 @@ class CardController < ActionController::Base
96
84
 
97
85
  # ----------( HELPER METHODS ) -------------
98
86
 
99
- def new_or_fetch_card
100
- opts = card_opts
101
- if params[:action] == 'create'
102
- # FIXME: we currently need a "new" card to catch duplicates
103
- # (otherwise save will just act like a normal update)
104
- # We may need a "#create" instance method to handle this checking?
105
- Card.new opts
106
- else
107
- mark = params[:id] || opts[:name]
108
- Card.fetch mark, new: opts
109
- end
110
- end
111
-
112
- def card_opts
113
- opts = (params[:card] || {}).clone
114
- # clone so that original params remain unaltered. need deeper clone?
115
- opts[:type] ||= params[:type] if params[:type]
116
- # for /new/:type shortcut. we should fix and deprecate this.
117
- opts[:name] ||= params[:id].to_s.tr('_', ' ')
118
- # move handling to Card::Name?
119
- opts
120
- end
121
-
122
- def determine_id
123
- case
124
- when needs_setup?
125
- prepare_setup_card!
126
- when params[:card] && params[:card][:name]
127
- params[:card][:name]
128
- when Card::Format.tagged(params[:view], :unknown_ok)
129
- ''
130
- else
131
- Card.global_setting(:home) || 'Home'
132
- end
133
- end
134
-
135
- def needs_setup?
136
- Card::Auth.needs_setup? && Card::Env.html?
137
- end
138
-
139
- def prepare_setup_card!
140
- params[:card] = { type_id: Card.default_accounted_type_id }
141
- params[:view] = 'setup'
142
- ''
143
- end
144
-
145
- def validate_id_encoding id
146
- # we should find the place where we produce these bad urls
147
- id.valid_encoding? ? id : id.force_encoding('ISO-8859-1').encode('UTF-8')
148
- end
149
-
150
- def send_asset path, filename, options={}
151
- if filename.include? '../'
152
- # for security, block relative paths
153
- raise Wagn::BadAddress
154
- else
155
- send_file File.join(path, filename), options
156
- end
157
- end
158
-
159
- def card_redirect url
160
- url = card_url url # make sure we have absolute url
161
- if ajax?
162
- # lets client reset window location (not just receive redirected response)
163
- # formerly used 303 response, but that gave IE the fits
164
- render json: { redirect: url }
165
- else
166
- redirect_to url
167
- end
168
- end
169
-
170
87
  def handle
171
88
  card.act(success: true) do
172
89
  yield ? render_success : render_errors
@@ -174,119 +91,43 @@ class CardController < ActionController::Base
174
91
  end
175
92
 
176
93
  def render_success
94
+ success = Card::Env.success
177
95
  success.name_context = @card.cardname
178
- return card_redirect success.to_url if !ajax? || success.hard_redirect?
179
- return render text: success.target if success.target.is_a? String
180
-
181
- @card = success.target
182
- update_params_for_success
183
- @card.select_action_by_params params
184
- show
185
- end
186
-
187
- def render_errors
188
- # FIXME: should prioritize certain error classes
189
- code = nil
190
- card.errors.each do |key, _msg|
191
- break if (code = Card.error_codes[key])
96
+ if !Card::Env.ajax? || success.hard_redirect?
97
+ card_redirect success.to_url
98
+ elsif success.target.is_a? String
99
+ render text: success.target
100
+ else
101
+ reset_card success.target
102
+ show
192
103
  end
193
- view, status = code || [:errors, 422]
194
- show view, status
195
104
  end
196
105
 
197
106
  def show view=nil, status=200
198
107
  card.action = :read
199
108
  card.content = card.last_draft_content if use_draft?
200
109
 
201
- view ||= params[:view]
202
- slot_opts = (params[:slot] || {}).deep_symbolize_keys
110
+ formatname = format_from_params
111
+ format = card.format formatname
203
112
 
204
- format = format_from_params
205
- formatter = card.format(format.to_sym)
206
- result = card.act { formatter.page view, slot_opts }
207
- status = formatter.error_status || status
113
+ view ||= params[:view]
114
+ result = card.act do
115
+ format.page view, page_opts_from_params
116
+ end
208
117
 
209
- deliver format, result, status
118
+ status = format.error_status || status
119
+ deliver formatname, result, status
210
120
  end
211
121
 
212
- def deliver format, result, status
213
- if format == :file && status == 200
214
- send_file(*result)
215
- elsif status == 302
216
- card_redirect result
217
- else
218
- args = { text: result, status: status }
219
- args[:content_type] = 'text/text' if format == :file
220
- render args
221
- end
122
+ def render_errors
123
+ view, status = Card::Error.view_and_status(card) || [:errors, 422]
124
+ show view, status
222
125
  end
223
126
 
224
127
  rescue_from StandardError do |exception|
225
128
  Rails.logger.info "exception = #{exception.class}: #{exception.message}"
226
-
227
129
  @card ||= Card.new
228
130
  Card::Error.current = exception
229
- view =
230
-
231
- case exception
232
- ## arguably the view and status should be defined in the error class;
233
- ## some are redundantly defined in view
234
- when Card::Oops, Card::BadQuery
235
- card.errors.add :exception, exception.message
236
- # these error messages are visible to end users and are generally not
237
- # treated as bugs.
238
- # Probably want to rename accordingly.
239
- :errors
240
- when Card::PermissionDenied
241
- :denial
242
- when Card::NotFound, ActiveRecord::RecordNotFound,
243
- ActionController::MissingFile
244
- :not_found
245
- when Wagn::BadAddress
246
- :bad_address
247
- else
248
- # the following indicate a code problem and therefore require full
249
- # logging
250
- @card.notable_exception_raised
251
-
252
- if ActiveRecord::RecordInvalid === exception
253
- :errors
254
- # could also just check non-production mode...
255
- elsif Rails.logger.level == 0
256
- raise exception
257
- else
258
- :server_error
259
- end
260
- end
261
-
262
- show view
263
- end
264
-
265
- def ajax?
266
- Card::Env.ajax?
267
- end
268
-
269
- def success
270
- Card::Env[:success]
271
- end
272
-
273
- def format_from_params
274
- return :file if params[:explicit_file]
275
- format = request.parameters[:format]
276
- return :file unless Card::Format.registered.member?(format) # unknown format
277
- format
278
- end
279
-
280
- def update_params_for_success
281
- if success.soft_redirect?
282
- self.params = success.params
283
- else
284
- # need tests. insure we get slot, main...
285
- params.merge! success.params
286
- end
287
- end
288
-
289
- def use_draft?
290
- params[:edit_draft] && card.drafts.present?
131
+ show Card::Error.exception_view(@card, exception)
291
132
  end
292
133
  end
@@ -2,49 +2,49 @@
2
2
 
3
3
  Decko::Engine.routes.draw do
4
4
  # most common
5
- root 'card#read'
5
+ root "card#read"
6
6
  get "#{Decko::Engine.config.files_web_path}/:id/:rev_id(-:size).:format" =>
7
- 'card#read', id: /[^-]+/, rev_id: /[^-]+/, explicit_file: true
7
+ "card#read", id: /[^-]+/, rev_id: /[^-]+/, explicit_file: true
8
8
  get "#{Decko::Engine.config.files_web_path}/:id(-:size)-:rev_id.:format" =>
9
- 'card#read', id: /[^-]+/, explicit_file: true # deprecated
10
- get 'assets/*filename' => 'card#asset'
11
- get 'javascripts/*filename' => 'card#asset'
12
- get 'jasmine/*filename' => 'card#asset'
9
+ "card#read", id: /[^-]+/, explicit_file: true # deprecated
10
+ get "assets/*filename" => "card#asset"
11
+ get "javascripts/*filename" => "card#asset"
12
+ get "jasmine/*filename" => "card#asset"
13
13
 
14
- get 'recent(.:format)' => 'card#read', id: ':recent' # obviate by making links use codename
14
+ get "recent(.:format)" => "card#read", id: ":recent" # obviate by making links use codename
15
15
  # match ':view:(:id(.:format))' => 'card#read', via: :get
16
- get '(/wagn)/:id(.:format)' => 'card#read' # /wagn is deprecated
16
+ get "(/wagn)/:id(.:format)" => "card#read" # /wagn is deprecated
17
17
 
18
18
  # RESTful
19
- post '/' => 'card#create'
20
- put '/' => 'card#update'
21
- delete '/' => 'card#delete'
19
+ post "/" => "card#create"
20
+ put "/" => "card#update"
21
+ delete "/" => "card#delete"
22
22
 
23
- match ':id(.:format)' => 'card#create', via: :post
24
- match ':id(.:format)' => 'card#update', via: :put
25
- match ':id(.:format)' => 'card#delete', via: :delete
23
+ match ":id(.:format)" => "card#create", via: :post
24
+ match ":id(.:format)" => "card#update", via: :put
25
+ match ":id(.:format)" => "card#delete", via: :delete
26
26
 
27
27
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~
28
28
  # legacy
29
- get 'new/:type' => 'card#read', view: 'new'
30
- get 'card/:view(/:id(.:format))' => 'card#read', view: /new|options|edit/
31
-
32
- get 'account/signin' => 'card#read', id: ':signin'
33
- get 'account/signout' => 'card#delete', id: ':signin'
34
- get 'account/signup' => 'card#read', view: 'new', card: { type_code: :signup }
35
- get 'account/invite' => 'card#read', view: 'new', card: { type_code: :signup }
36
- get 'account/accept' => 'card#read', view: 'edit', card: { type_code: :signup }
29
+ get "new/:type" => "card#read", view: "new"
30
+ get "card/:view(/:id(.:format))" => "card#read", view: /new|options|edit/
31
+
32
+ get "account/signin" => "card#read", id: ":signin"
33
+ get "account/signout" => "card#delete", id: ":signin"
34
+ get "account/signup" => "card#read", view: "new", card: { type_code: :signup }
35
+ get "account/invite" => "card#read", view: "new", card: { type_code: :signup }
36
+ get "account/accept" => "card#read", view: "edit", card: { type_code: :signup }
37
37
  # use type_code rather than id because in some cases (eg populating test data) routes must get loaded without loading Card
38
38
 
39
- get 'admin/stats' => 'card#read', id: ':stats'
40
- get 'admin/:task' => 'card#update', id: ':all'
39
+ get "admin/stats" => "card#read", id: ":stats"
40
+ get "admin/:task" => "card#update", id: ":all"
41
41
  # ~~~~~~~~~~~~~~~~~~~~~~~~~~
42
42
 
43
43
  # standard non-RESTful
44
- get '(card)/:action(/:id(.:format))' => 'card', action: /create|read|update|delete|asset/
45
- match '(card)/create(/:id(.:format))' => 'card#create', via: [:post, :patch]
46
- match '(card)/update(/:id(.:format))' => 'card#update', via: [:post, :put, :patch]
47
- match '(card)/delete(/:id(.:format))' => 'card#delete', via: :delete
44
+ get "(card)/:action(/:id(.:format))" => "card", action: /create|read|update|delete|asset/
45
+ match "(card)/create(/:id(.:format))" => "card#create", via: [:post, :patch]
46
+ match "(card)/update(/:id(.:format))" => "card#update", via: [:post, :put, :patch]
47
+ match "(card)/delete(/:id(.:format))" => "card#delete", via: :delete
48
48
  # other
49
- get '*id' => 'card#read', view: 'bad_address'
49
+ get "*id" => "card#read", view: "bad_address"
50
50
  end
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
- ENV['RSPEC'] = 'true' # allows autotest to discover rspec
3
- ENV['AUTOTEST'] = 'true' # allows autotest to run w/ color on linux
4
- system (RUBY_PLATFORM =~ /mswin|mingw/ ? 'autotest.bat' : 'autotest'), *ARGV
2
+ ENV["RSPEC"] = "true" # allows autotest to discover rspec
3
+ ENV["AUTOTEST"] = "true" # allows autotest to run w/ color on linux
4
+ system (RUBY_PLATFORM =~ /mswin|mingw/ ? "autotest.bat" : "autotest"), *ARGV
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
3
 
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
6
- require 'rails/commands'
4
+ APP_PATH = File.expand_path("../../config/application", __FILE__)
5
+ require File.expand_path("../../config/boot", __FILE__)
6
+ require "rails/commands"
@@ -1,8 +1,8 @@
1
1
  #!/usr/local/bin/ruby
2
2
 
3
3
  STDOUT.sync = true
4
- errors_filename = './log/err.out'
5
- err_out = File.new(errors_filename, 'a')
4
+ errors_filename = "./log/err.out"
5
+ err_out = File.new(errors_filename, "a")
6
6
 
7
7
  ARGF.each_line do |l|
8
8
  error_section = false
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
3
 
4
- APP_PATH = File.expand_path('../../config/application', __FILE__)
5
- require File.expand_path('../../config/boot', __FILE__)
6
- require 'wagn/commands'
4
+ APP_PATH = File.expand_path("../../config/application", __FILE__)
5
+ require File.expand_path("../../config/boot", __FILE__)
6
+ require "wagn/commands"
@@ -4,359 +4,383 @@ describe CardController do
4
4
  routes { Decko::Engine.routes }
5
5
 
6
6
  include Capybara::DSL
7
- describe '- route generation' do
8
- it 'should recognize type' do
7
+ describe "- route generation" do
8
+ def card_route_to opts={}
9
+ route_to opts.merge(controller: "card")
10
+ end
11
+
12
+ it "should recognize type" do
9
13
  # all_routes = Rails.application.routes.routes
10
14
  # require 'rails/application/route_inspector'
11
15
  # warn "rountes#{ENV['CONTROLLER']}:\n" + Rails::Application::RouteInspector.new.format(all_routes, ENV['CONTROLLER'])* "\n"
12
16
 
13
- expect(get: '/new/Phrase').to route_to(controller: 'card', action: 'read', type: 'Phrase', view: 'new')
17
+ expect(get: "/new/Phrase")
18
+ .to card_route_to(action: "read", type: "Phrase", view: "new")
14
19
  end
15
20
 
16
- it 'should recognize .rss on /recent' do
17
- expect(get: '/recent.rss').to route_to(controller: 'card', action: 'read', id: ':recent', format: 'rss')
21
+ it "should recognize .rss on /recent" do
22
+ expect(get: "/recent.rss")
23
+ .to card_route_to(action: "read", id: ":recent", format: "rss")
18
24
  end
19
25
 
20
- it 'should handle RESTful posts' do
21
- expect(put: '/mycard').to route_to(controller: 'card', action: 'update', id: 'mycard')
22
- expect(put: '/').to route_to(controller: 'card', action: 'update')
26
+ it "should handle RESTful posts" do
27
+ expect(put: "/mycard").to card_route_to(action: "update", id: "mycard")
28
+ expect(put: "/").to card_route_to(action: "update")
23
29
  end
24
30
 
25
- it 'handle asset requests' do
26
- expect(get: '/asset/application.js').to route_to(controller: 'card', action: 'asset', id: 'application', format: 'js')
31
+ it "handle asset requests" do
32
+ expect(get: "/asset/application.js")
33
+ .to card_route_to(action: "asset", id: "application", format: "js")
27
34
  end
28
35
 
29
- ['/wagn', ''].each do |prefix|
36
+ ["/wagn", ""].each do |prefix|
30
37
  describe "routes prefixed with '#{prefix}'" do
31
- it 'should recognize .rss format' do
32
- expect(get: "#{prefix}/*recent.rss").to route_to(
33
- controller: 'card', action: 'read', id: '*recent', format: 'rss'
34
- )
38
+ it "should recognize .rss format" do
39
+ expect(get: "#{prefix}/*recent.rss")
40
+ .to card_route_to(action: "read", id: "*recent", format: "rss")
35
41
  end
36
42
 
37
- it 'should recognize .xml format' do
38
- expect(get: "#{prefix}/*recent.xml").to route_to(
39
- controller: 'card', action: 'read', id: '*recent', format: 'xml'
40
- )
43
+ it "should recognize .xml format" do
44
+ expect(get: "#{prefix}/*recent.xml")
45
+ .to card_route_to(action: "read", id: "*recent", format: "xml")
41
46
  end
42
47
 
43
- it 'should accept cards without dots' do
44
- expect(get: "#{prefix}/random").to route_to(
45
- controller: 'card', action: 'read', id: 'random'
46
- )
48
+ it "should accept cards without dots" do
49
+ expect(get: "#{prefix}/random")
50
+ .to card_route_to(action: "read", id: "random")
47
51
  end
48
52
  end
49
53
  end
50
54
  end
51
55
 
52
- describe '#create' do
56
+ describe "#create" do
53
57
  before do
54
- login_as 'joe_user'
58
+ login_as "joe_user"
55
59
  end
56
60
 
57
61
  # FIXME: several of these tests go all the way to DB,
58
62
  # which means they're closer to integration than unit tests.
59
63
  # maybe think about refactoring to use mocks etc. to reduce
60
64
  # test dependencies.
61
- it 'creates cards' do
65
+ it "creates cards" do
62
66
  post :create, card: {
63
- name: 'NewCardFoo',
64
- type: 'Basic',
65
- content: 'Bananas'
67
+ name: "NewCardFoo",
68
+ type: "Basic",
69
+ content: "Bananas"
66
70
  }
67
71
  assert_response 302
68
- c = Card['NewCardFoo']
72
+ c = Card["NewCardFoo"]
69
73
  expect(c.type_code).to eq(:basic)
70
- expect(c.content).to eq('Bananas')
74
+ expect(c.content).to eq("Bananas")
71
75
  end
72
76
 
73
- it 'handles permission denials' do
77
+ it "handles permission denials" do
74
78
  post :create, card: {
75
- name: 'LackPerms',
76
- type: 'Html'
79
+ name: "LackPerms",
80
+ type: "Html"
77
81
  }
78
82
  assert_response 403
79
- expect(Card['LackPerms']).to be_nil
83
+ expect(Card["LackPerms"]).to be_nil
80
84
  end
81
85
 
82
86
  # no controller-specific handling. move test elsewhere
83
- it 'creates cardtype cards' do
84
- xhr :post, :create, card: { 'content' => 'test', type: 'Cardtype', name: 'Editor' }
85
- expect(assigns['card']).not_to be_nil
87
+ it "creates cardtype cards" do
88
+ xhr :post, :create,
89
+ card: { "content" => "test", type: "Cardtype", name: "Editor" }
90
+ expect(assigns["card"]).not_to be_nil
86
91
  assert_response 200
87
- c = Card['Editor']
92
+ c = Card["Editor"]
88
93
  expect(c.type_code).to eq(:cardtype)
89
94
  end
90
95
 
91
96
  # no controller-specific handling. move test elsewhere
92
- it 'pulls deleted cards from trash' do
93
- @c = Card.create! name: 'Problem', content: 'boof'
97
+ it "pulls deleted cards from trash" do
98
+ @c = Card.create! name: "Problem", content: "boof"
94
99
  @c.delete!
95
- post :create, card: { 'name' => 'Problem', 'type' => 'Phrase', 'content' => 'noof' }
100
+ post :create,
101
+ card: {
102
+ "name" => "Problem", "type" => "Phrase", "content" => "noof"
103
+ }
96
104
  assert_response 302
97
- c = Card['Problem']
105
+ c = Card["Problem"]
98
106
  expect(c.type_code).to eq(:phrase)
99
107
  end
100
108
 
101
- context 'multi-create' do
102
- it 'catches missing name error' do
103
- post :create, 'card' => {
104
- 'name' => '',
105
- 'type' => 'Fruit',
106
- 'subcards' => { '+text' => { 'content' => '<p>abraid</p>' } }
107
- }, 'view' => 'open'
109
+ context "multi-create" do
110
+ it "catches missing name error" do
111
+ post :create, "card" => {
112
+ "name" => "",
113
+ "type" => "Fruit",
114
+ "subcards" => { "+text" => { "content" => "<p>abraid</p>" } }
115
+ }, "view" => "open"
108
116
  assert_response 422
109
- expect(assigns['card'].errors[:name].first).to eq("can't be blank")
117
+ expect(assigns["card"].errors[:name].first).to eq("can't be blank")
110
118
  end
111
119
 
112
- it 'creates card with subcards' do
113
- login_as 'joe_admin'
114
- xhr :post, :create, success: 'REDIRECT: /', card: {
115
- name: 'Gala',
116
- type: 'Fruit',
120
+ it "creates card with subcards" do
121
+ login_as "joe_admin"
122
+ xhr :post, :create, success: "REDIRECT: /", card: {
123
+ name: "Gala",
124
+ type: "Fruit",
117
125
  subcards: {
118
- '+kind' => { content: 'apple' },
119
- '+color' => { type: 'Phrase', content: 'red' }
126
+ "+kind" => { content: "apple" },
127
+ "+color" => { type: "Phrase", content: "red" }
120
128
  }
121
129
  }
122
130
  assert_response 200
123
- expect(Card['Gala']).not_to be_nil
124
- expect(Card['Gala+kind'].content).to eq('apple')
125
- expect(Card['Gala+color'].type_name).to eq('Phrase')
131
+ expect(Card["Gala"]).not_to be_nil
132
+ expect(Card["Gala+kind"].content).to eq("apple")
133
+ expect(Card["Gala+color"].type_name).to eq("Phrase")
126
134
  end
127
135
  end
128
136
 
129
- it 'renders errors if create fails' do
130
- post :create, 'card' => { 'name' => 'Joe User' }
137
+ it "renders errors if create fails" do
138
+ post :create, "card" => { "name" => "Joe User" }
131
139
  assert_response 422
132
140
  end
133
141
 
134
- it 'redirects to thanks if present' do
135
- login_as 'joe_admin'
136
- xhr :post, :create, success: 'REDIRECT: /thank_you', card: { 'name' => 'Wombly' }
142
+ it "redirects to thanks if present" do
143
+ login_as "joe_admin"
144
+ xhr :post, :create, success: "REDIRECT: /thank_you",
145
+ card: { "name" => "Wombly" }
137
146
  assert_response 200
138
147
  json = JSON.parse response.body
139
- expect(json['redirect']).to match(/^http.*\/thank_you$/)
148
+ expect(json["redirect"]).to match(/^http.*\/thank_you$/)
140
149
  end
141
150
 
142
- it 'redirects to card if thanks is blank' do
143
- login_as 'joe_admin'
144
- post :create, success: 'REDIRECT: _self', 'card' => { 'name' => 'Joe+boop' }
145
- assert_redirected_to '/Joe+boop'
151
+ it "redirects to card if thanks is blank" do
152
+ login_as "joe_admin"
153
+ post :create, success: "REDIRECT: _self",
154
+ "card" => { "name" => "Joe+boop" }
155
+ assert_redirected_to "/Joe+boop"
146
156
  end
147
157
 
148
- it 'redirects to previous' do
158
+ it "redirects to previous" do
149
159
  # Fruits (from shared_data) are anon creatable but not readable
150
160
  login_as :anonymous
151
- post :create, { success: 'REDIRECT: *previous', 'card' => { 'type' => 'Fruit', name: 'papaya' } }, history: ['/blam']
152
- assert_redirected_to '/blam'
161
+ post :create, { success: "REDIRECT: *previous",
162
+ "card" => { "type" => "Fruit", name: "papaya" } },
163
+ history: ["/blam"]
164
+ assert_redirected_to "/blam"
153
165
  end
154
166
  end
155
167
 
156
- describe '#read' do
157
- it 'works for basic request' do
158
- get :read, id: 'Sample_Basic'
168
+ describe "#read" do
169
+ it "works for basic request" do
170
+ get :read, id: "Sample_Basic"
159
171
  expect(response.body.match(/\<body[^>]*\>/im)).to be_truthy
160
- # have_selector broke in commit 8d3bf2380eb8197410e962304c5e640fced684b9, presumably because of a gem (like capybara?)
172
+ # have_selector broke in commit 8d3bf2380eb8197410e962304c5e640fced684b9,
173
+ # presumably because of a gem (like capybara?)
161
174
  # response.should have_selector('body')
162
175
  assert_response :success
163
- expect('Sample Basic').to eq(assigns['card'].name)
176
+ expect("Sample Basic").to eq(assigns["card"].name)
164
177
  end
165
178
 
166
- it 'handles nonexistent card with create permission' do
167
- login_as 'joe_user'
168
- get :read, id: 'Sample_Fako'
179
+ it "handles nonexistent card with create permission" do
180
+ login_as "joe_user"
181
+ get :read, id: "Sample_Fako"
169
182
  assert_response :success
170
183
  end
171
184
 
172
- it 'handles nonexistent card without create permissions' do
173
- get :read, id: 'Sample_Fako'
185
+ it "handles nonexistent card without create permissions" do
186
+ get :read, id: "Sample_Fako"
174
187
  assert_response 404
175
188
  end
176
189
 
177
- it 'handles nonexistent card ids' do
178
- get :read, id: '~9999999'
190
+ it "handles nonexistent card ids" do
191
+ get :read, id: "~9999999"
179
192
  assert_response 404
180
193
  end
181
194
 
182
- it 'returns denial when no read permission' do
195
+ it "returns denial when no read permission" do
183
196
  Card::Auth.as_bot do
184
- Card.create! name: 'Strawberry', type: 'Fruit' # only admin can read
197
+ Card.create! name: "Strawberry", type: "Fruit" # only admin can read
185
198
  end
186
- get :read, id: 'Strawberry'
199
+ get :read, id: "Strawberry"
187
200
  assert_response 403
188
- get :read, id: 'Strawberry', format: 'txt'
201
+ get :read, id: "Strawberry", format: "txt"
189
202
  assert_response 403
190
203
  end
191
204
 
192
- context 'view = new' do
205
+ context "view = new" do
193
206
  before do
194
- login_as 'joe_user'
207
+ login_as "joe_user"
195
208
  end
196
209
 
197
- it 'should work on index' do
198
- get :read, view: 'new'
199
- expect(assigns['card'].name).to eq('')
200
- assert_response :success, 'response should succeed'
201
- assert_equal Card::BasicID, assigns['card'].type_id, '@card type should == Basic'
210
+ it "should work on index" do
211
+ get :read, view: "new"
212
+ expect(assigns["card"].name).to eq("")
213
+ assert_response :success, "response should succeed"
214
+ assert_equal Card::BasicID, assigns["card"].type_id,
215
+ "@card type should == Basic"
202
216
  end
203
217
 
204
- it 'new with name' do
205
- post :read, card: { name: 'BananaBread' }, view: 'new'
206
- assert_response :success, 'response should succeed'
207
- assert_equal 'BananaBread', assigns['card'].name, '@card.name should == BananaBread'
218
+ it "new with name" do
219
+ post :read, card: { name: "BananaBread" }, view: "new"
220
+ assert_response :success, "response should succeed"
221
+ assert_equal "BananaBread", assigns["card"].name,
222
+ "@card.name should == BananaBread"
208
223
  end
209
224
 
210
- it 'new with existing name' do
211
- get :read, card: { name: 'A' }, view: 'new'
212
- assert_response :success, 'response should succeed' # really?? how come this is ok?
225
+ it "new with existing name" do
226
+ get :read, card: { name: "A" }, view: "new"
227
+ # really?? how come this is ok?
228
+ assert_response :success, "response should succeed"
213
229
  end
214
230
 
215
- it 'new with type_code' do
216
- post :read, card: { type: 'Date' }, view: 'new'
217
- assert_response :success, 'response should succeed'
218
- assert_equal Card::DateID, assigns['card'].type_id, '@card type should == Date'
231
+ it "new with type_code" do
232
+ post :read, card: { type: "Date" }, view: "new"
233
+ assert_response :success, "response should succeed"
234
+ assert_equal Card::DateID, assigns["card"].type_id,
235
+ "@card type should == Date"
219
236
  end
220
237
 
221
- it 'new should work for creatable nonviewable cardtype' do
238
+ it "new should work for creatable nonviewable cardtype" do
222
239
  login_as :anonymous
223
- get :read, type: 'Fruit', view: 'new'
240
+ get :read, type: "Fruit", view: "new"
224
241
  assert_response :success
225
242
  end
226
243
 
227
- it 'should use card params name over id in new cards' do
228
- get :read, id: 'my_life', card: { name: 'My LIFE' }, view: 'new'
229
- expect(assigns['card'].name).to eq('My LIFE')
244
+ it "should use card params name over id in new cards" do
245
+ get :read, id: "my_life", card: { name: "My LIFE" }, view: "new"
246
+ expect(assigns["card"].name).to eq("My LIFE")
230
247
  end
231
248
  end
232
249
 
233
- context 'css' do
250
+ context "css" do
234
251
  before do
235
252
  @all_style = Card["#{Card[:all].name}+#{Card[:style].name}"]
236
- @all_style.reset_machine_output!
253
+ @all_style.reset_machine_output
237
254
  end
238
255
 
239
- it 'creates missing machine output file' do
240
- args = { id: @all_style.machine_output_card.name, format: 'css', explicit_file: true }
256
+ it "creates missing machine output file" do
257
+ args = { id: @all_style.machine_output_card.name,
258
+ format: "css",
259
+ explicit_file: true }
241
260
  get :read, args
242
- output_card = Card["#{Card[:all].name}+#{Card[:style].name}+#{Card[:machine_output].name}"]
261
+ # output_card = Card[:all, :style, :machine_output]
243
262
  expect(response).to redirect_to(@all_style.machine_output_url)
244
263
  get :read, args
245
264
  expect(response.status).to eq(200)
246
265
  end
247
266
  end
248
267
 
249
- context 'file' do
268
+ context "file" do
250
269
  before do
251
270
  Card::Auth.as_bot do
252
- Card.create name: 'mao2', type_code: 'image', image: File.new(File.join FIXTURES_PATH, 'mao2.jpg')
253
- Card.create name: 'mao2+*self+*read', content: '[[Administrator]]'
271
+ Card.create name: "mao2", type_code: "image",
272
+ image: File.new(File.join(FIXTURES_PATH, "mao2.jpg"))
273
+ Card.create name: "mao2+*self+*read", content: "[[Administrator]]"
254
274
  end
255
275
  end
256
276
 
257
- it 'handles image with no read permission' do
258
- get :read, id: 'mao2'
259
- assert_response 403, 'should deny html card view'
260
- get :read, id: 'mao2', format: 'jpg'
261
- assert_response 403, 'should deny simple file view'
277
+ it "handles image with no read permission" do
278
+ get :read, id: "mao2"
279
+ assert_response 403, "should deny html card view"
280
+ get :read, id: "mao2", format: "jpg"
281
+ assert_response 403, "should deny simple file view"
262
282
  end
263
283
 
264
- it 'handles image with read permission' do
265
- login_as 'joe_admin'
266
- get :read, id: 'mao2'
284
+ it "handles image with read permission" do
285
+ login_as "joe_admin"
286
+ get :read, id: "mao2"
267
287
  assert_response 200
268
- get :read, id: 'mao2', format: 'jpg'
288
+ get :read, id: "mao2", format: "jpg"
269
289
  assert_response 200
270
290
  end
271
291
  end
272
292
  end
273
293
 
274
- describe '#asset' do
275
- it 'serves file' do
276
- filename = 'asset-test.txt'
277
- args = { id: filename, format: 'txt', explicit_file: true }
278
- path = File.join(Decko::Engine.paths['gem-assets'].existent.first, filename)
279
- File.open(path, 'w') { |f| f.puts 'test' }
294
+ describe "#asset" do
295
+ it "serves file" do
296
+ filename = "asset-test.txt"
297
+ args = { id: filename, format: "txt", explicit_file: true }
298
+ path =
299
+ File.join(Decko::Engine.paths["gem-assets"].existent.first, filename)
300
+ File.open(path, "w") { |f| f.puts "test" }
280
301
  args = { filename: filename.to_s }
281
302
  visit "/assets/#{filename}"
282
303
  expect(page.body).to eq "test\n"
283
304
  FileUtils.rm path
284
305
  end
285
306
 
286
- it 'denies access to other directories' do
287
- args = { filename: '/../../Gemfile' }
307
+ it "denies access to other directories" do
308
+ args = { filename: "/../../Gemfile" }
288
309
  get :asset, args
289
310
  expect(response.status).to eq(404)
290
311
  end
291
312
  end
292
313
 
293
- describe 'unit tests' do
314
+ describe "unit tests" do
294
315
  before do
295
- @simple_card = Card['Sample Basic']
296
- login_as 'joe_user'
316
+ @simple_card = Card["Sample Basic"]
317
+ login_as "joe_user"
297
318
  end
298
319
 
299
- describe '#update' do
300
- it 'works' do
320
+ describe "#update" do
321
+ it "works" do
301
322
  xhr :post, :update, id: "~#{@simple_card.id}",
302
- card: { content: 'brand new content' }
303
- assert_response :success, 'edited card'
304
- assert_equal 'brand new content', Card['Sample Basic'].content, 'content was updated'
323
+ card: { content: "brand new content" }
324
+ assert_response :success, "edited card"
325
+ assert_equal "brand new content", Card["Sample Basic"].content,
326
+ "content was updated"
305
327
  end
306
328
 
307
- it 'rename without update references should work' do
308
- f = Card.create! type: 'Cardtype', name: 'Apple'
329
+ it "rename without update references should work" do
330
+ f = Card.create! type: "Cardtype", name: "Apple"
309
331
  xhr :post, :update, id: "~#{f.id}", card: {
310
- name: 'Newt',
311
- update_referers: 'false'
332
+ name: "Newt",
333
+ update_referers: "false"
312
334
  }
313
- expect(assigns['card'].errors.empty?).not_to be_nil
335
+ expect(assigns["card"].errors.empty?).not_to be_nil
314
336
  assert_response :success
315
- expect(Card['Newt']).not_to be_nil
337
+ expect(Card["Newt"]).not_to be_nil
316
338
  end
317
339
 
318
- it 'update type_code' do
319
- xhr :post, :update, id: "~#{@simple_card.id}", card: { type: 'Date' }
320
- assert_response :success, 'changed card type'
321
- expect(Card['Sample Basic'].type_code).to eq(:date)
340
+ it "update type_code" do
341
+ xhr :post, :update, id: "~#{@simple_card.id}", card: { type: "Date" }
342
+ assert_response :success, "changed card type"
343
+ expect(Card["Sample Basic"].type_code).to eq(:date)
322
344
  end
323
345
  end
324
346
 
325
- describe 'delete' do
326
- it 'works' do
327
- c = Card.create(name: 'Boo', content: 'booya')
347
+ describe "delete" do
348
+ it "works" do
349
+ c = Card.create(name: "Boo", content: "booya")
328
350
  post :delete, id: "~#{c.id}"
329
351
  assert_response :redirect
330
- expect(Card['Boo']).to eq(nil)
352
+ expect(Card["Boo"]).to eq(nil)
331
353
  end
332
354
 
333
355
  # FIXME: this should probably be files in the spot for a delete test
334
- it 'returns to previous undeleted card after deletion' do
356
+ it "returns to previous undeleted card after deletion" do
335
357
  t1 = t2 = nil
336
358
  Card::Auth.as_bot do
337
- t1 = Card.create! name: 'Testable1', content: 'hello'
338
- t2 = Card.create! name: 'Testable1+bandana', content: 'world'
359
+ t1 = Card.create! name: "Testable1", content: "hello"
360
+ t2 = Card.create! name: "Testable1+bandana", content: "world"
339
361
  end
340
362
 
341
363
  get :read, id: t1.key
342
364
  get :read, id: t2.key
343
365
 
344
- post :delete, id: '~' + t2.id.to_s
366
+ post :delete, id: "~" + t2.id.to_s
345
367
  assert_nil Card[t2.name]
346
368
  assert_redirected_to "/#{t1.name}"
347
369
 
348
- post :delete, id: '~' + t1.id.to_s
349
- assert_redirected_to '/'
370
+ post :delete, id: "~" + t1.id.to_s
371
+ assert_redirected_to "/"
350
372
  assert_nil Card[t1.name]
351
373
  end
352
374
  end
353
375
 
354
- it 'should comment' do
376
+ it "should comment" do
355
377
  Card::Auth.as_bot do
356
- Card.create name: 'basicname+*self+*comment', content: '[[Anyone Signed In]]'
378
+ Card.create name: "basicname+*self+*comment",
379
+ content: "[[Anyone Signed In]]"
357
380
  end
358
- post :update, id: 'basicname', card: { comment: " and more\n \nsome lines\n\n" }
359
- cont = Card['basicname'].content
381
+ post :update, id: "basicname",
382
+ card: { comment: " and more\n \nsome lines\n\n" }
383
+ cont = Card["basicname"].content
360
384
  expect(cont).to match(/basiccontent/)
361
385
  expect(cont).to match(/some lines/)
362
386
  end