js-routes 1.4.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.eslintrc.js +15 -0
  3. data/.gitignore +5 -0
  4. data/.nvmrc +1 -0
  5. data/.travis.yml +37 -30
  6. data/Appraisals +16 -13
  7. data/CHANGELOG.md +95 -0
  8. data/Rakefile +6 -2
  9. data/Readme.md +220 -88
  10. data/VERSION_2_UPGRADE.md +66 -0
  11. data/app/assets/javascripts/js-routes.js.erb +1 -1
  12. data/gemfiles/{rails40.gemfile → rails40_sprockets_2.gemfile} +1 -1
  13. data/gemfiles/{rails40_sprockets3.gemfile → rails40_sprockets_3.gemfile} +0 -0
  14. data/gemfiles/{rails41.gemfile → rails41_sprockets_2.gemfile} +1 -1
  15. data/gemfiles/{rails41_sprockets3.gemfile → rails41_sprockets_3.gemfile} +0 -0
  16. data/gemfiles/{rails32.gemfile → rails42_sprockets_2.gemfile} +2 -2
  17. data/gemfiles/{rails42_sprockets3.gemfile → rails42_sprockets_3.gemfile} +1 -1
  18. data/gemfiles/{rails50_sprockets3.gemfile → rails50_sprockets_3.gemfile} +1 -1
  19. data/gemfiles/rails51_sprockets_3.gemfile +8 -0
  20. data/gemfiles/rails52_sprockets_3.gemfile +8 -0
  21. data/js-routes.gemspec +9 -6
  22. data/lib/js_routes/engine.rb +6 -18
  23. data/lib/js_routes/version.rb +1 -1
  24. data/lib/js_routes.rb +329 -171
  25. data/lib/routes.d.ts +79 -0
  26. data/lib/routes.js +499 -485
  27. data/lib/routes.ts +732 -0
  28. data/lib/tasks/js_routes.rake +8 -2
  29. data/package.json +37 -0
  30. data/spec/dummy/app/assets/config/manifest.js +2 -0
  31. data/spec/js_routes/default_serializer_spec.rb +19 -3
  32. data/spec/js_routes/{amd_compatibility_spec.rb → module_types/amd_spec.rb} +1 -9
  33. data/spec/js_routes/module_types/cjs_spec.rb +15 -0
  34. data/spec/js_routes/module_types/dts/routes.spec.d.ts +114 -0
  35. data/spec/js_routes/module_types/dts/test.spec.ts +56 -0
  36. data/spec/js_routes/module_types/dts_spec.rb +111 -0
  37. data/spec/js_routes/module_types/esm_spec.rb +45 -0
  38. data/spec/js_routes/{generated_javascript_spec.rb → module_types/umd_spec.rb} +33 -27
  39. data/spec/js_routes/options_spec.rb +92 -50
  40. data/spec/js_routes/rails_routes_compatibility_spec.rb +107 -45
  41. data/spec/js_routes/zzz_last_post_rails_init_spec.rb +19 -8
  42. data/spec/spec_helper.rb +45 -42
  43. data/spec/support/routes.rb +19 -14
  44. data/spec/tsconfig.json +4 -0
  45. data/tsconfig.json +28 -0
  46. data/yarn.lock +2145 -0
  47. metadata +47 -34
  48. data/gemfiles/rails42.gemfile +0 -8
  49. data/gemfiles/rails50.gemfile +0 -8
  50. data/lib/routes.js.coffee +0 -386
@@ -2,13 +2,26 @@ require 'spec_helper'
2
2
 
3
3
  describe JsRoutes, "options" do
4
4
 
5
+ let(:generated_js) do
6
+ JsRoutes.generate({
7
+ module_type: nil,
8
+ namespace: 'Routes',
9
+ **_options
10
+ })
11
+ end
12
+
5
13
  before(:each) do
6
14
  evaljs(_presetup) if _presetup
7
15
  with_warnings(_warnings) do
8
- evaljs(JsRoutes.generate(_options))
16
+ evaljs(generated_js)
17
+ App.routes.default_url_options = _options[:default_url_options] || {}
9
18
  end
10
19
  end
11
20
 
21
+ after(:each) do
22
+ App.routes.default_url_options = {}
23
+ end
24
+
12
25
  let(:_presetup) { nil }
13
26
  let(:_options) { {} }
14
27
  let(:_warnings) { true }
@@ -32,9 +45,10 @@ describe JsRoutes, "options" do
32
45
  let(:_presetup){ %q(var myCustomSerializer = 1) }
33
46
  let(:_options) { {:serializer => "myCustomSerializer"} }
34
47
 
35
- it "should set configurable serializer" do
36
- # expect to use default
37
- expect(evaljs(%q(Routes.inboxes_path({a: 1})))).to eql("/inboxes?a=1")
48
+ it "should throw error" do
49
+ expect {
50
+ evaljs(%q(Routes.inboxes_path({a: 1})))
51
+ }.to raise_error(js_error_class)
38
52
  end
39
53
  end
40
54
 
@@ -81,6 +95,18 @@ describe JsRoutes, "options" do
81
95
  expect(evaljs("Routes.inboxes_path")).to be_nil
82
96
  end
83
97
 
98
+ context "with camel_case option" do
99
+ let(:_options) { {include: /^admin_/, camel_case: true} }
100
+
101
+ it "should exclude specified routes from file" do
102
+ expect(evaljs("Routes.adminUsersPath()")).not_to be_nil
103
+ end
104
+
105
+ it "should not exclude routes not under specified pattern" do
106
+ expect(evaljs("Routes.inboxesPath")).to be_nil
107
+ end
108
+ end
109
+
84
110
  context "for rails engine" do
85
111
  let(:_options) { {:include => /^blog_app_posts/} }
86
112
 
@@ -134,12 +160,14 @@ describe JsRoutes, "options" do
134
160
  let(:_options) { {:default_url_options => {format: "json"}} }
135
161
  let(:_warnings) { nil }
136
162
 
137
- it "should render routing with default_format" do
138
- expect(evaljs("Routes.inbox_path(1)")).to eq(test_routes.inbox_path(1, :format => "json"))
139
- end
163
+ if Rails.version >= "5"
164
+ it "should render routing with default_format" do
165
+ expect(evaljs("Routes.inbox_path(1)")).to eq(test_routes.inbox_path(1))
166
+ end
140
167
 
141
- it "should render routing with default_format and zero object" do
142
- expect(evaljs("Routes.inbox_path(0)")).to eq(test_routes.inbox_path(0, :format => "json"))
168
+ it "should render routing with default_format and zero object" do
169
+ expect(evaljs("Routes.inbox_path(0)")).to eq(test_routes.inbox_path(0))
170
+ end
143
171
  end
144
172
 
145
173
  it "should override default_format when spefified implicitly" do
@@ -147,13 +175,11 @@ describe JsRoutes, "options" do
147
175
  end
148
176
 
149
177
  it "should override nullify implicitly when specified implicitly" do
150
- expect(evaljs("Routes.inbox_path(1, {format: null})")).to eq(test_routes.inbox_path(1))
178
+ expect(evaljs("Routes.inbox_path(1, {format: null})")).to eq(test_routes.inbox_path(1, format: nil))
151
179
  end
152
180
 
153
-
154
181
  it "shouldn't require the format" do
155
- pending if Rails.version < "4.0"
156
- expect(evaljs("Routes.json_only_path()")).to eq(test_routes.json_only_path(:format => 'json'))
182
+ expect(evaljs("Routes.json_only_path()")).to eq(test_routes.json_only_path)
157
183
  end
158
184
  end
159
185
 
@@ -162,36 +188,45 @@ describe JsRoutes, "options" do
162
188
  expect(evaljs("Routes.no_format_path({format: 'json'})")).to eq(test_routes.no_format_path(format: 'json'))
163
189
  end
164
190
 
165
- describe "when namespace option is specified" do
191
+ describe "namespace option" do
166
192
  let(:_options) { {:namespace => "PHM"} }
167
193
  it "should use this namespace for routing" do
168
194
  expect(evaljs("window.Routes")).to be_nil
169
195
  expect(evaljs("PHM.inbox_path")).not_to be_nil
170
196
  end
171
- end
172
197
 
173
- describe "when nested namespace option is specified" do
174
- context "and defined on client" do
175
- let(:_presetup) { "window.PHM = {}" }
176
- let(:_options) { {:namespace => "PHM.Routes"} }
198
+ context "is nil" do
199
+ let(:_options) { {:namespace => nil, include: /^inbox$/} }
177
200
  it "should use this namespace for routing" do
178
- expect(evaljs("PHM.Routes.inbox_path")).not_to be_nil
201
+ evaljs("window.zz = #{generated_js}")
202
+ expect(evaljs("window.zz.inbox_path")).not_to be_nil
179
203
  end
204
+
180
205
  end
181
206
 
182
- context "but undefined on client" do
183
- let(:_options) { {:namespace => "PHM.Routes"} }
184
- it "should initialize namespace" do
185
- expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
207
+ describe "is nested" do
208
+ context "and defined on client" do
209
+ let(:_presetup) { "window.PHM = {}" }
210
+ let(:_options) { {:namespace => "PHM.Routes"} }
211
+ it "should use this namespace for routing" do
212
+ expect(evaljs("PHM.Routes.inbox_path")).not_to be_nil
213
+ end
214
+ end
215
+
216
+ context "but undefined on client" do
217
+ let(:_options) { {:namespace => "PHM.Routes"} }
218
+ it "should initialize namespace" do
219
+ expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
220
+ end
186
221
  end
187
- end
188
222
 
189
- context "and some parts are defined" do
190
- let(:_presetup) { "window.PHM = { Utils: {} };" }
191
- let(:_options) { {:namespace => "PHM.Routes"} }
192
- it "should not overwrite existing parts" do
193
- expect(evaljs("window.PHM.Utils")).not_to be_nil
194
- expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
223
+ context "and some parts are defined" do
224
+ let(:_presetup) { "window.PHM = { Utils: {} };" }
225
+ let(:_options) { {:namespace => "PHM.Routes"} }
226
+ it "should not overwrite existing parts" do
227
+ expect(evaljs("window.PHM.Utils")).not_to be_nil
228
+ expect(evaljs("window.PHM.Routes.inbox_path")).not_to be_nil
229
+ end
195
230
  end
196
231
  end
197
232
  end
@@ -201,14 +236,14 @@ describe JsRoutes, "options" do
201
236
  context "provided" do
202
237
  let(:_options) { { :default_url_options => { :optional_id => "12", :format => "json" } } }
203
238
  it "should use this opions to fill optional parameters" do
204
- expect(evaljs("Routes.things_path()")).to eq(test_routes.things_path(:optional_id => 12, :format => "json"))
239
+ expect(evaljs("Routes.things_path()")).to eq(test_routes.things_path)
205
240
  end
206
241
  end
207
242
 
208
243
  context "not provided" do
209
244
  let(:_options) { { :default_url_options => { :format => "json" } } }
210
245
  it "breaks" do
211
- expect(evaljs("Routes.foo_all_path()")).to eq(test_routes.foo_all_path(:format => "json"))
246
+ expect(evaljs("Routes.foo_all_path()")).to eq(test_routes.foo_all_path)
212
247
  end
213
248
  end
214
249
  end
@@ -216,7 +251,7 @@ describe JsRoutes, "options" do
216
251
  context "with required route parts" do
217
252
  let(:_options) { {:default_url_options => {:inbox_id => "12"}} }
218
253
  it "should use this opions to fill optional parameters" do
219
- expect(evaljs("Routes.inbox_messages_path()")).to eq(test_routes.inbox_messages_path(:inbox_id => 12))
254
+ expect(evaljs("Routes.inbox_messages_path()")).to eq(test_routes.inbox_messages_path)
220
255
  end
221
256
  end
222
257
 
@@ -248,7 +283,7 @@ describe JsRoutes, "options" do
248
283
  end
249
284
 
250
285
  it "should remove it by params" do
251
- expect(evaljs("Routes.inbox_path(1, {trailing_slash: false})")).to eq(test_routes.inbox_path(1))
286
+ expect(evaljs("Routes.inbox_path(1, {trailing_slash: false})")).to eq(test_routes.inbox_path(1, trailing_slash: false))
252
287
  end
253
288
  end
254
289
 
@@ -349,8 +384,8 @@ describe JsRoutes, "options" do
349
384
  expect(evaljs("Routes.sso_url()")).to eq("http://sso.example.com:3000" + test_routes.sso_path)
350
385
  end
351
386
 
352
- it "does not override port when specified in route" do
353
- expect(evaljs("Routes.portals_url()")).to eq("http://example.com:8080#{test_routes.portals_path}")
387
+ it "does not override parts when specified in route" do
388
+ expect(evaljs("Routes.secret_root_url()")).to eq(test_routes.secret_root_url)
354
389
  end
355
390
  end
356
391
 
@@ -358,9 +393,6 @@ describe JsRoutes, "options" do
358
393
  let(:_options) { { :camel_case => true, :url_links => true, :default_url_options => {:host => "example.com"} } }
359
394
  it "should generate path and url links" do
360
395
  expect(evaljs("Routes.inboxUrl(1)")).to eq("http://example.com#{test_routes.inbox_path(1)}")
361
- expect(evaljs("Routes.newSessionUrl()")).to eq("https://example.com#{test_routes.new_session_path}")
362
- expect(evaljs("Routes.ssoUrl()")).to eq(test_routes.sso_url)
363
- expect(evaljs("Routes.portalsUrl()")).to eq("http://example.com:8080#{test_routes.portals_path}")
364
396
  end
365
397
  end
366
398
 
@@ -368,9 +400,6 @@ describe JsRoutes, "options" do
368
400
  let(:_options) { { :prefix => "/api", :url_links => true, :default_url_options => {:host => 'example.com'} } }
369
401
  it "should generate path and url links" do
370
402
  expect(evaljs("Routes.inbox_url(1)")).to eq("http://example.com/api#{test_routes.inbox_path(1)}")
371
- expect(evaljs("Routes.new_session_url()")).to eq("https://example.com/api#{test_routes.new_session_path}")
372
- expect(evaljs("Routes.sso_url()")).to eq("http://sso.example.com/api#{test_routes.sso_path}")
373
- expect(evaljs("Routes.portals_url()")).to eq("http://example.com:8080/api#{test_routes.portals_path}")
374
403
  end
375
404
  end
376
405
 
@@ -378,9 +407,6 @@ describe JsRoutes, "options" do
378
407
  let(:_options) { { :compact => true, :url_links => true, :default_url_options => {:host => 'example.com'} } }
379
408
  it "does not affect url helpers" do
380
409
  expect(evaljs("Routes.inbox_url(1)")).to eq("http://example.com#{test_routes.inbox_path(1)}")
381
- expect(evaljs("Routes.new_session_url()")).to eq("https://example.com#{test_routes.new_session_path}")
382
- expect(evaljs("Routes.sso_url()")).to eq(test_routes.sso_url)
383
- expect(evaljs("Routes.portals_url()")).to eq("http://example.com:8080#{test_routes.portals_path}")
384
410
  end
385
411
  end
386
412
  end
@@ -408,20 +434,27 @@ describe JsRoutes, "options" do
408
434
  expect(evaljs("Routes.inbox_url(1)")).to eq("http://current.example.com#{test_routes.inbox_path(1)}")
409
435
  expect(evaljs("Routes.inbox_url(1, { test_key: \"test_val\" })")).to eq("http://current.example.com#{test_routes.inbox_path(1, :test_key => "test_val")}")
410
436
  expect(evaljs("Routes.new_session_url()")).to eq("https://current.example.com#{test_routes.new_session_path}")
411
- expect(evaljs("Routes.sso_url()")).to eq("http://sso.example.com#{test_routes.sso_path}")
412
437
 
413
438
  end
414
439
 
440
+ it "doesn't use current when specified in the route" do
441
+ expect(evaljs("Routes.sso_url()")).to eq(test_routes.sso_url)
442
+ end
443
+
415
444
  it "uses host option as an argument" do
416
- expect(evaljs("Routes.portals_url({host: 'another.com'})")).to eq(test_routes.portals_url(host: 'another.com'))
445
+ expect(evaljs("Routes.secret_root_url({host: 'another.com'})")).to eq(test_routes.secret_root_url(host: 'another.com'))
417
446
  end
418
447
 
419
448
  it "uses port option as an argument" do
420
- expect(evaljs("Routes.portals_url({host: 'localhost', port: 8080})")).to eq(test_routes.portals_url(host: 'localhost', port: 8080))
449
+ expect(evaljs("Routes.secret_root_url({host: 'localhost', port: 8080})")).to eq(test_routes.secret_root_url(host: 'localhost', port: 8080))
421
450
  end
422
451
 
423
452
  it "uses protocol option as an argument" do
424
- expect(evaljs("Routes.portals_url({host: 'localhost', protocol: 'https'})")).to eq(test_routes.portals_url(protocol: 'https', host: 'localhost'))
453
+ expect(evaljs("Routes.secret_root_url({host: 'localhost', protocol: 'https'})")).to eq(test_routes.secret_root_url(protocol: 'https', host: 'localhost'))
454
+ end
455
+
456
+ it "uses subdomain option as an argument" do
457
+ expect(evaljs("Routes.secret_root_url({subdomain: 'custom'})")).to eq(test_routes.secret_root_url(subdomain: 'custom'))
425
458
  end
426
459
  end
427
460
  end
@@ -478,4 +511,13 @@ describe JsRoutes, "options" do
478
511
  expect(evaljs("Routes.posts_path()")).not_to be_nil
479
512
  end
480
513
  end
514
+
515
+ describe "documentation option" do
516
+ let(:_options) { {documentation: false} }
517
+
518
+ it "disables documentation generation" do
519
+ expect(generated_js).not_to include("@param")
520
+ expect(generated_js).not_to include("@returns")
521
+ end
522
+ end
481
523
  end
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
  describe JsRoutes, "compatibility with Rails" do
4
4
 
5
5
  before(:each) do
6
- evaljs(JsRoutes.generate({}))
6
+ evaljs(JsRoutes.generate({module_type: nil, namespace: 'Routes'}))
7
7
  end
8
8
 
9
9
  it "should generate collection routing" do
@@ -14,15 +14,31 @@ describe JsRoutes, "compatibility with Rails" do
14
14
  expect(evaljs("Routes.inbox_path(1)")).to eq(test_routes.inbox_path(1))
15
15
  end
16
16
 
17
- it "should raise error if required argument is not passed" do
17
+ it "should raise error if required argument is not passed", :aggregate_failures do
18
18
  expect { evaljs("Routes.thing_path()") }
19
- .to raise_error('Route parameter missing: id')
19
+ .to raise_error(/Route missing required keys: id/)
20
20
  expect { evaljs("Routes.search_path()") }
21
- .to raise_error('Route parameter missing: q')
21
+ .to raise_error(/Route missing required keys: q/)
22
22
  expect { evaljs("Routes.book_path()") }
23
- .to raise_error('Route parameter missing: title')
23
+ .to raise_error(/Route missing required keys: section, title/)
24
24
  expect { evaljs("Routes.book_title_path()") }
25
- .to raise_error('Route parameter missing: title')
25
+ .to raise_error(/Route missing required keys: title/)
26
+
27
+ expect( evaljs("try {Routes.thing_path()} catch (e) { e.name }") ).to eq('ParametersMissing')
28
+ expect( evaljs("try {Routes.thing_path()} catch (e) { e.keys }") ).to eq(['id'])
29
+ end
30
+
31
+ it "should produce error stacktraces including function names" do
32
+ stacktrace = evaljs("
33
+ (function(){
34
+ try {
35
+ Routes.thing_path()
36
+ } catch(e) {
37
+ return e.stack;
38
+ }
39
+ })()
40
+ ")
41
+ expect(stacktrace).to include "thing_path"
26
42
  end
27
43
 
28
44
  it "should support 0 as a member parameter" do
@@ -57,6 +73,10 @@ describe JsRoutes, "compatibility with Rails" do
57
73
  expect(evaljs("Routes.inbox_path(1, {expanded: true, anchor: 'hello'})")).to eq(test_routes.inbox_path(1, :expanded => true, :anchor => "hello"))
58
74
  end
59
75
 
76
+ it "should support required parameters given as options hash" do
77
+ expect(evaljs("Routes.search_path({q: 'hello'})")).to eq(test_routes.search_path(:q => 'hello'))
78
+ end
79
+
60
80
  it "should use irregular ActiveSupport pluralizations" do
61
81
  expect(evaljs("Routes.budgies_path()")).to eq(test_routes.budgies_path)
62
82
  expect(evaljs("Routes.budgie_path(1)")).to eq(test_routes.budgie_path(1))
@@ -64,6 +84,16 @@ describe JsRoutes, "compatibility with Rails" do
64
84
  expect(evaljs("Routes.budgie_descendents_path(1)")).to eq(test_routes.budgie_descendents_path(1))
65
85
  end
66
86
 
87
+ it "should support route with parameters containing symbols that need URI-encoding", :aggregate_failures do
88
+ expect(evaljs("Routes.inbox_path('#hello')")).to eq(test_routes.inbox_path('#hello'))
89
+ expect(evaljs("Routes.inbox_path('some param')")).to eq(test_routes.inbox_path('some param'))
90
+ expect(evaljs("Routes.inbox_path('some param with more & more encode symbols')")).to eq(test_routes.inbox_path('some param with more & more encode symbols'))
91
+ end
92
+ it "should support route with parameters containing symbols not need URI-encoding", :aggregate_failures do
93
+ expect(evaljs("Routes.inbox_path(':some_id')")).to eq(test_routes.inbox_path(':some_id'))
94
+ expect(evaljs("Routes.inbox_path('.+')")).to eq(test_routes.inbox_path('.+'))
95
+ end
96
+
67
97
  describe "when route has defaults" do
68
98
  it "should support route default format" do
69
99
  expect(evaljs("Routes.api_purchases_path()")).to eq(test_routes.api_purchases_path)
@@ -83,6 +113,7 @@ describe JsRoutes, "compatibility with Rails" do
83
113
 
84
114
  it "doesn't apply defaults to path" do
85
115
  expect(evaljs("Routes.with_defaults_path()")).to eq(test_routes.with_defaults_path)
116
+ expect(evaljs("Routes.with_defaults_path({format: 'json'})")).to eq(test_routes.with_defaults_path(format: 'json'))
86
117
  end
87
118
  end
88
119
 
@@ -104,6 +135,11 @@ describe JsRoutes, "compatibility with Rails" do
104
135
  it "should support single route mapping" do
105
136
  expect(evaljs("Routes.support_path({page: 3})")).to eq(test_routes.support_path(:page => 3))
106
137
  end
138
+
139
+ it 'works' do
140
+ expect(evaljs("Routes.planner_manage_path({locale: 'ua'})")).to eq(planner_routes.manage_path(locale: 'ua'))
141
+ expect(evaljs("Routes.planner_manage_path()")).to eq(planner_routes.manage_path)
142
+ end
107
143
  end
108
144
 
109
145
  it "shouldn't require the format" do
@@ -122,7 +158,7 @@ describe JsRoutes, "compatibility with Rails" do
122
158
  expect(evaljs("Routes.root_path()")).to eq(test_routes.root_path)
123
159
  end
124
160
 
125
- describe "get paramters" do
161
+ describe "get parameters" do
126
162
  it "should support simple get parameters" do
127
163
  expect(evaljs("Routes.inbox_path(1, {format: 'json', lang: 'ua', q: 'hello'})")).to eq(test_routes.inbox_path(1, :lang => "ua", :q => "hello", :format => "json"))
128
164
  end
@@ -131,6 +167,19 @@ describe JsRoutes, "compatibility with Rails" do
131
167
  expect(evaljs("Routes.inbox_path(1, {hello: ['world', 'mars']})")).to eq(test_routes.inbox_path(1, :hello => [:world, :mars]))
132
168
  end
133
169
 
170
+ context "object without prototype" do
171
+ before(:each) do
172
+ evaljs("let params = Object.create(null); params.q = 'hello';")
173
+ evaljs("let inbox = Object.create(null); inbox.to_param = 1;")
174
+ end
175
+
176
+ it "should still work correctly" do
177
+ expect(evaljs("Routes.inbox_path(inbox, params)")).to eq(
178
+ test_routes.inbox_path(1, q: "hello")
179
+ )
180
+ end
181
+ end
182
+
134
183
  it "should support nested get parameters" do
135
184
  expect(evaljs("Routes.inbox_path(1, {format: 'json', env: 'test', search: { category_ids: [2,5], q: 'hello'}})")).to eq(
136
185
  test_routes.inbox_path(1, :env => 'test', :search => {:category_ids => [2,5], :q => "hello"}, :format => "json")
@@ -145,6 +194,9 @@ describe JsRoutes, "compatibility with Rails" do
145
194
  expect(evaljs("Routes.inboxes_path({uri: 'http://example.com'})")).to eq(test_routes.inboxes_path(:uri => 'http://example.com'))
146
195
  end
147
196
 
197
+ it "should support nested object null parameters" do
198
+ expect(evaljs("Routes.inboxes_path({hello: {world: null}})")).to eq(test_routes.inboxes_path(:hello => {:world => nil}))
199
+ end
148
200
  end
149
201
 
150
202
 
@@ -157,14 +209,18 @@ describe JsRoutes, "compatibility with Rails" do
157
209
  expect(evaljs("Routes.book_path(['thrillers'], 1)")).to eq(test_routes.book_path(['thrillers'], 1))
158
210
  end
159
211
 
160
- it "should bee support routes globbing as array" do
212
+ it "should support routes globbing as array" do
161
213
  expect(evaljs("Routes.book_path([1, 2, 3], 1)")).to eq(test_routes.book_path([1, 2, 3], 1))
162
214
  end
163
215
 
164
- it "should bee support routes globbing as hash" do
216
+ it "should support routes globbing with slash" do
165
217
  expect(evaljs("Routes.book_path('a_test/b_test/c_test', 1)")).to eq(test_routes.book_path('a_test/b_test/c_test', 1))
166
218
  end
167
219
 
220
+ it "should support routes globbing as hash" do
221
+ expect(evaljs("Routes.book_path('a%b', 1)")).to eq(test_routes.book_path('a%b', 1))
222
+ end
223
+
168
224
  it "should support routes globbing as array with optional params" do
169
225
  expect(evaljs("Routes.book_path([1, 2, 3, 5], 1, {c: '1'})")).to eq(test_routes.book_path([1, 2, 3, 5], 1, { :c => "1" }))
170
226
  end
@@ -176,14 +232,6 @@ describe JsRoutes, "compatibility with Rails" do
176
232
  it "should support routes globbing in book_title route as array with optional params" do
177
233
  expect(evaljs("Routes.book_title_path('john', ['thrillers', 'comedian'], {some_key: 'some_value'})")).to eq(test_routes.book_title_path('john', ['thrillers', 'comedian'], {:some_key => 'some_value'}))
178
234
  end
179
-
180
- it "should support required paramters given as options hash" do
181
- expect(evaljs("Routes.search_path({q: 'hello'})")).to eq(test_routes.search_path(:q => 'hello'))
182
- end
183
-
184
- it "should support nested object null parameters" do
185
- expect(evaljs("Routes.inboxes_path({hello: {world: null}})")).to eq(test_routes.inboxes_path(:hello => {:world => nil}))
186
- end
187
235
  end
188
236
 
189
237
  context "using optional path fragments" do
@@ -199,6 +247,15 @@ describe JsRoutes, "compatibility with Rails" do
199
247
  expect(evaljs("Routes.things_path({ q: 'hello' })")).to eq(test_routes.things_path(q: 'hello'))
200
248
  end
201
249
 
250
+ it "treats false as absent optional part" do
251
+ pending("https://github.com/rails/rails/issues/42280")
252
+ expect(evaljs("Routes.things_path(false)")).to eq(test_routes.things_path(false))
253
+ end
254
+
255
+ it "treats false as absent optional part when default is specified" do
256
+ expect(evaljs("Routes.campaigns_path(false)")).to eq(test_routes.campaigns_path(false))
257
+ end
258
+
202
259
  it "should not require the optional parts as arguments" do
203
260
  expect(evaljs("Routes.thing_path(null, 5)")).to eq(test_routes.thing_path(nil, 5))
204
261
  end
@@ -209,7 +266,7 @@ describe JsRoutes, "compatibility with Rails" do
209
266
 
210
267
  it "should raise error when passing non-full list of arguments and some query params" do
211
268
  expect { evaljs("Routes.thing_path(5, {q: 'hello'})") }
212
- .to raise_error('Route parameter missing: id')
269
+ .to raise_error(/Route missing required keys: id/)
213
270
  end
214
271
 
215
272
  it "should treat null as non-given optional part" do
@@ -221,19 +278,13 @@ describe JsRoutes, "compatibility with Rails" do
221
278
  end
222
279
 
223
280
  it "should skip leading and trailing optional parts" do
224
- skip if Rails.version < '4'
225
281
  expect(evaljs("Routes.thing_deep_path(1, 2)")).to eq(test_routes.thing_deep_path(1, 2))
226
282
  end
227
283
  end
228
284
 
229
285
  context "and including them" do
230
- if Rails.version < '4'
231
- it "should fail when insufficient arguments are given" do
232
- expect { evaljs("Routes.thing_deep_path(1)")}
233
- .to raise_error('Route parameter missing: second_required')
234
- expect { evaljs("Routes.thing_deep_path(1,2)")}
235
- .to raise_error('Route parameter missing: third_required')
236
- end
286
+ it "should fail when insufficient arguments are given" do
287
+ expect { evaljs("Routes.thing_deep_path(2)") }.to raise_error(/Route missing required keys: third_required/)
237
288
  end
238
289
 
239
290
  it "should include the optional parts" do
@@ -245,6 +296,7 @@ describe JsRoutes, "compatibility with Rails" do
245
296
  expect(evaljs("Routes.thing_deep_path(3, { first_optional: 1, second_required: 2 })")).to eq(test_routes.thing_deep_path(3, first_optional: 1, second_required: 2))
246
297
  expect(evaljs("Routes.thing_deep_path(3, { first_optional: 1, second_required: 2, forth_optional: 4 })")).to eq(test_routes.thing_deep_path(3, first_optional: 1, second_required: 2, forth_optional: 4))
247
298
  expect(evaljs("Routes.thing_deep_path(4, { first_optional: 1, second_required: 2, third_required: 3 })")).to eq(test_routes.thing_deep_path(4, first_optional: 1, second_required: 2, third_required: 3))
299
+ expect(evaljs("Routes.thing_deep_path(2, 3)")).to eq(test_routes.thing_deep_path(2, 3))
248
300
  expect(evaljs("Routes.thing_deep_path(1, 2, { third_required: 3 })")).to eq(test_routes.thing_deep_path(1, 2, third_required: 3))
249
301
  expect(evaljs("Routes.thing_deep_path(1,2, {third_required: 3, q: 'bogdan'})")).to eq(test_routes.thing_deep_path(1,2, {third_required: 3, q: 'bogdan'}))
250
302
  expect(evaljs("Routes.thing_deep_path(1, 2, { forth_optional: 4, third_required: 3 })")).to eq(test_routes.thing_deep_path(1, 2, forth_optional: 4, third_required: 3))
@@ -281,27 +333,22 @@ describe JsRoutes, "compatibility with Rails" do
281
333
  evaljs("Routes.inbox_path()")
282
334
  }.to raise_error(js_error_class)
283
335
  end
336
+
284
337
  it "should throw Exception if required parameter is not defined" do
285
338
  expect {
286
339
  evaljs("Routes.inbox_path(null)")
287
340
  }.to raise_error(js_error_class)
288
341
  end
289
342
 
290
- it "should throw Exceptions if when there is too many parameters" do
291
- expect {
292
- evaljs("Routes.inbox_path(1,2,3)")
293
- }.to raise_error(js_error_class)
294
- end
295
-
296
- it "should throw Exceptions if when pass id with null" do
343
+ it "should throw Exception if required parameter is not defined" do
297
344
  expect {
298
- evaljs("Routes.inbox_path({id: null})")
345
+ evaljs("Routes.inbox_path(undefined)")
299
346
  }.to raise_error(js_error_class)
300
347
  end
301
348
 
302
- it "should throw Exceptions if when pass to_param with null" do
349
+ it "should throw Exceptions if when there is too many parameters" do
303
350
  expect {
304
- evaljs("Routes.inbox_path({to_param: null})")
351
+ evaljs("Routes.inbox_path(1,2,3)")
305
352
  }.to raise_error(js_error_class)
306
353
  end
307
354
  end
@@ -320,8 +367,19 @@ describe JsRoutes, "compatibility with Rails" do
320
367
  let(:klass) { Struct.new(:id, :to_param) }
321
368
  let(:inbox) { klass.new(1,"my") }
322
369
 
370
+ it "should throw Exceptions if when pass id with null" do
371
+ expect {
372
+ evaljs("Routes.inbox_path({id: null})")
373
+ }.to raise_error(js_error_class)
374
+ end
375
+
376
+ it "should throw Exceptions if when pass to_param with null" do
377
+ expect {
378
+ evaljs("Routes.inbox_path({to_param: null})")
379
+ }.to raise_error(js_error_class)
380
+ end
323
381
  it "should support 0 as a to_param option" do
324
- expect(evaljs("Routes.inbox_path({to_param: 0})")).to eq(test_routes.inbox_path(0))
382
+ expect(evaljs("Routes.inbox_path({to_param: 0})")).to eq(test_routes.inbox_path(Struct.new(:to_param).new('0')))
325
383
  end
326
384
 
327
385
  it "should check for options special key" do
@@ -332,9 +390,6 @@ describe JsRoutes, "compatibility with Rails" do
332
390
  expect(evaljs("Routes.inbox_message_path(5, {id: 7, q: 'hello', _options: true})")).to eq(test_routes.inbox_message_path(5, id: 7, q: 'hello'))
333
391
  end
334
392
 
335
- it "should check for options special key" do
336
- end
337
-
338
393
  it "should support 0 as an id option" do
339
394
  expect(evaljs("Routes.inbox_path({id: 0})")).to eq(test_routes.inbox_path(0))
340
395
  end
@@ -361,6 +416,14 @@ describe JsRoutes, "compatibility with Rails" do
361
416
  )).to eq(test_routes.inbox_message_path(inbox, 2, :custom => true, :format => "json"))
362
417
  end
363
418
 
419
+ it "supports camel case property name" do
420
+ expect(evaljs("Routes.inbox_path({id: 1, toParam: 'my'})")).to eq(test_routes.inbox_path(inbox))
421
+ end
422
+
423
+ it "supports camel case method name" do
424
+ expect(evaljs("Routes.inbox_path({id: 1, toParam: function(){ return 'my';}})")).to eq(test_routes.inbox_path(inbox))
425
+ end
426
+
364
427
  context "when globbing" do
365
428
  it "should prefer to_param property over id property" do
366
429
  expect(evaljs("Routes.book_path({id: 1, to_param: 'my'}, 1)")).to eq(test_routes.book_path(inbox, 1))
@@ -380,6 +443,7 @@ describe JsRoutes, "compatibility with Rails" do
380
443
  )).to eq(test_routes.book_path(inbox, 2, :custom => true, :format => "json"))
381
444
  end
382
445
  end
446
+
383
447
  end
384
448
 
385
449
  context "when specs" do
@@ -400,15 +464,13 @@ describe JsRoutes, "compatibility with Rails" do
400
464
  end
401
465
  end
402
466
 
403
- describe "required_params" do
467
+ describe "requiredParams" do
404
468
  it "should show inbox spec" do
405
- expect(evaljs("Routes.inbox_path.required_params").to_a).to eq(["id"])
469
+ expect(evaljs("Routes.inbox_path.requiredParams()").to_a).to eq(["id"])
406
470
  end
407
471
 
408
472
  it "should show inbox message spec" do
409
- expect(evaljs("Routes.inbox_message_path.required_params").to_a).to eq(["inbox_id", "id"])
473
+ expect(evaljs("Routes.inbox_message_path.requiredParams()").to_a).to eq(["inbox_id", "id"])
410
474
  end
411
475
  end
412
-
413
-
414
476
  end
@@ -5,7 +5,7 @@
5
5
  require 'spec_helper'
6
6
  require "fileutils"
7
7
 
8
- describe "after Rails initialization" do
8
+ describe "after Rails initialization", :slow do
9
9
  NAME = Rails.root.join('app', 'assets', 'javascripts', 'routes.js').to_s
10
10
 
11
11
  def sprockets_v3?
@@ -43,6 +43,21 @@ describe "after Rails initialization" do
43
43
  expect(File.exists?(NAME)).to be_truthy
44
44
  end
45
45
 
46
+ it "should not rewrite routes file if nothing changed" do
47
+ routes_file_mtime = File.mtime(NAME)
48
+ JsRoutes.generate!(NAME)
49
+ expect(File.mtime(NAME)).to eq(routes_file_mtime)
50
+ end
51
+
52
+ it "should rewrite routes file if file content changed" do
53
+ # Change content of existed routes file (add space to the end of file).
54
+ File.open(NAME, 'a') { |f| f << ' ' }
55
+ routes_file_mtime = File.mtime(NAME)
56
+ sleep(1)
57
+ JsRoutes.generate!(NAME)
58
+ expect(File.mtime(NAME)).not_to eq(routes_file_mtime)
59
+ end
60
+
46
61
  context "JsRoutes::Engine" do
47
62
  TEST_ASSET_PATH = Rails.root.join('app','assets','javascripts','test.js')
48
63
 
@@ -78,7 +93,7 @@ describe "after Rails initialization" do
78
93
  Rails.application.config.assets.initialize_on_precompile = true
79
94
  end
80
95
  it "should render some javascript" do
81
- expect(evaluate(ctx, 'js-routes.js')).to match(/routes = /)
96
+ expect(evaluate(ctx, 'js-routes.js')).to match(/Utils\.define_module/)
82
97
  end
83
98
  end
84
99
  context "and not initialize on precompile" do
@@ -86,11 +101,7 @@ describe "after Rails initialization" do
86
101
  Rails.application.config.assets.initialize_on_precompile = false
87
102
  end
88
103
  it "should raise an exception if 3 version" do
89
- if 3 == Rails::VERSION::MAJOR
90
- expect { evaluate(ctx, 'js-routes.js') }.to raise_error(/Cannot precompile/)
91
- else
92
- expect(evaluate(ctx, 'js-routes.js')).to match(/routes = /)
93
- end
104
+ expect(evaluate(ctx, 'js-routes.js')).to match(/Utils\.define_module/)
94
105
  end
95
106
  end
96
107
 
@@ -111,7 +122,7 @@ describe "after Rails initialization" do
111
122
  end
112
123
  end
113
124
 
114
- describe "JSRoutes thread safety" do
125
+ describe "JSRoutes thread safety", :slow do
115
126
  before do
116
127
  begin
117
128
  Rails.application.initialize!