volt 0.9.6 → 0.9.7.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/CHANGELOG.md +26 -0
- data/Gemfile +6 -1
- data/README.md +2 -0
- data/Rakefile +1 -0
- data/app/volt/models/active_volt_instance.rb +8 -6
- data/app/volt/models/user.rb +11 -2
- data/app/volt/models/volt_app_property.rb +8 -0
- data/app/volt/tasks/query_tasks.rb +23 -31
- data/app/volt/tasks/store_tasks.rb +2 -2
- data/app/volt/tasks/volt_admin_tasks.rb +24 -0
- data/docs/UPGRADE_GUIDE.md +6 -0
- data/lib/volt.rb +19 -12
- data/lib/volt/boot.rb +1 -0
- data/lib/volt/cli.rb +19 -8
- data/lib/volt/cli/console.rb +0 -1
- data/lib/volt/cli/generators.rb +14 -3
- data/lib/volt/cli/migrate.rb +26 -0
- data/lib/volt/config.rb +17 -4
- data/lib/volt/controllers/http_controller.rb +12 -0
- data/lib/volt/data_stores/base_adaptor_client.rb +2 -2
- data/lib/volt/data_stores/base_adaptor_server.rb +2 -0
- data/lib/volt/data_stores/data_store.rb +20 -14
- data/lib/volt/extra_core/class.rb +28 -14
- data/lib/volt/extra_core/hash.rb +5 -0
- data/lib/volt/extra_core/string.rb +3 -1
- data/lib/volt/helpers/time.rb +9 -43
- data/lib/volt/helpers/time/calculations.rb +204 -0
- data/lib/volt/helpers/time/distance.rb +63 -0
- data/lib/volt/helpers/time/duration.rb +71 -0
- data/lib/volt/helpers/time/local_calculations.rb +49 -0
- data/lib/volt/helpers/time/local_volt_time.rb +23 -0
- data/lib/volt/helpers/time/numeric.rb +59 -0
- data/lib/volt/helpers/time/volt_time.rb +170 -0
- data/lib/volt/models.rb +5 -0
- data/lib/volt/models/array_model.rb +33 -6
- data/lib/volt/models/associations.rb +146 -23
- data/lib/volt/models/buffer.rb +38 -41
- data/lib/volt/models/cursor.rb +15 -0
- data/lib/volt/models/errors.rb +11 -0
- data/lib/volt/models/field_helpers.rb +108 -68
- data/lib/volt/models/helpers/array_model.rb +4 -0
- data/lib/volt/models/helpers/base.rb +8 -1
- data/lib/volt/models/helpers/change_helpers.rb +31 -12
- data/lib/volt/models/helpers/defaults.rb +15 -0
- data/lib/volt/models/location.rb +20 -6
- data/lib/volt/models/migrations/migration.rb +23 -0
- data/lib/volt/models/migrations/migration_runner.rb +146 -0
- data/lib/volt/models/model.rb +38 -1
- data/lib/volt/models/permissions.rb +8 -1
- data/lib/volt/models/persistors/array_store.rb +87 -8
- data/lib/volt/models/persistors/base.rb +19 -0
- data/lib/volt/models/persistors/model_store.rb +1 -1
- data/lib/volt/models/persistors/page.rb +4 -1
- data/lib/volt/models/persistors/query/query_identifier.rb +102 -0
- data/lib/volt/models/persistors/query/query_listener.rb +57 -12
- data/lib/volt/models/root_models/root_models.rb +19 -0
- data/lib/volt/models/url.rb +11 -2
- data/lib/volt/models/validations/validations.rb +5 -2
- data/lib/volt/models/validators/type_validator.rb +11 -0
- data/lib/volt/models/validators/unique_validator.rb +2 -2
- data/lib/volt/page/bindings/attribute_binding.rb +23 -1
- data/lib/volt/page/targets/attribute_section.rb +7 -0
- data/lib/volt/page/targets/binding_document/component_node.rb +44 -18
- data/lib/volt/page/targets/binding_document/tag_node.rb +41 -0
- data/lib/volt/page/tasks.rb +16 -8
- data/lib/volt/queries/live_query.rb +109 -0
- data/lib/volt/queries/live_query_pool.rb +58 -0
- data/lib/volt/queries/live_subquery.rb +0 -0
- data/lib/volt/queries/query_association_splitter.rb +31 -0
- data/lib/volt/queries/query_diff.rb +100 -0
- data/lib/volt/queries/query_runner.rb +110 -0
- data/lib/volt/queries/query_subscription.rb +80 -0
- data/lib/volt/queries/query_subscription_pool.rb +37 -0
- data/lib/volt/reactive/eventable.rb +8 -0
- data/lib/volt/reactive/reactive_array.rb +0 -4
- data/lib/volt/router/routes.rb +81 -31
- data/lib/volt/server/message_bus/base_message_bus.rb +9 -3
- data/lib/volt/server/message_bus/peer_to_peer.rb +6 -6
- data/lib/volt/server/message_bus/peer_to_peer/server_tracker.rb +1 -1
- data/lib/volt/server/middleware/default_middleware_stack.rb +12 -8
- data/lib/volt/server/rack/component_paths.rb +31 -4
- data/lib/volt/server/rack/http_content_types.rb +62 -0
- data/lib/volt/server/rack/http_resource.rb +1 -1
- data/lib/volt/server/rack/index_files.rb +8 -1
- data/lib/volt/server/rack/opal_files.rb +16 -1
- data/lib/volt/server/rack/sprockets_helpers_setup.rb +32 -1
- data/lib/volt/server/socket_connection_handler.rb +16 -7
- data/lib/volt/server/template_handlers/sprockets_component_handler.rb +5 -3
- data/lib/volt/spec/capybara.rb +4 -3
- data/lib/volt/spec/setup.rb +5 -0
- data/lib/volt/tasks/dispatcher.rb +3 -1
- data/lib/volt/utils/data_transformer.rb +4 -4
- data/lib/volt/utils/ejson.rb +19 -6
- data/lib/volt/utils/promise_extensions.rb +1 -1
- data/lib/volt/utils/time_opal_patch.rb +749 -0
- data/lib/volt/utils/time_patch.rb +11 -4
- data/lib/volt/version.rb +1 -1
- data/lib/volt/volt/app.rb +19 -11
- data/lib/volt/volt/properties.rb +24 -0
- data/lib/volt/volt/server_setup/app.rb +30 -7
- data/lib/volt/volt/users.rb +15 -3
- data/spec/apps/kitchen_sink/Gemfile +5 -1
- data/spec/apps/kitchen_sink/app/main/config/routes.rb +1 -0
- data/spec/apps/kitchen_sink/app/main/controllers/save_controller.rb +1 -1
- data/spec/apps/kitchen_sink/app/main/controllers/server/simple_http_controller.rb +4 -0
- data/spec/apps/kitchen_sink/app/main/controllers/todos_controller.rb +4 -2
- data/spec/apps/kitchen_sink/app/main/models/post.rb +0 -1
- data/spec/apps/kitchen_sink/app/main/models/todo.rb +4 -0
- data/spec/apps/kitchen_sink/app/main/views/mailers/reset_password.html +10 -0
- data/spec/apps/kitchen_sink/app/main/views/todos/index.html +2 -0
- data/spec/apps/kitchen_sink/config/app.rb +2 -0
- data/spec/apps/migrations/config/db/migrations/1445111704_migration1.rb +7 -0
- data/spec/apps/migrations/config/db/migrations/1445113517_migration2.rb +7 -0
- data/spec/apps/migrations/config/db/migrations/1445115200_migration3.rb +7 -0
- data/spec/extra_core/class_spec.rb +10 -0
- data/spec/helpers/distance_spec.rb +35 -0
- data/spec/helpers/duration_spec.rb +160 -0
- data/spec/helpers/volt_time_spec.rb +275 -0
- data/spec/integration/callbacks_spec.rb +2 -1
- data/spec/integration/http_endpoints_spec.rb +4 -0
- data/spec/integration/save_spec.rb +1 -1
- data/spec/integration/todos_spec.rb +7 -5
- data/spec/models/array_model_spec.rb +17 -3
- data/spec/models/associations_spec.rb +48 -1
- data/spec/models/field_helpers_spec.rb +7 -3
- data/spec/models/migrations/migration_runner_spec.rb +69 -0
- data/spec/models/model_spec.rb +42 -8
- data/spec/models/permissions_spec.rb +20 -8
- data/spec/models/persistors/array_store_spec.rb +18 -0
- data/spec/models/persistors/page_spec.rb +15 -10
- data/spec/models/persistors/store_spec.rb +13 -3
- data/spec/models/url_spec.rb +4 -3
- data/spec/models/user_spec.rb +6 -3
- data/spec/models/user_validation_spec.rb +3 -3
- data/spec/models/validations_spec.rb +4 -0
- data/spec/models/validators/block_validations_spec.rb +9 -5
- data/spec/models/validators/email_validator_spec.rb +2 -0
- data/spec/models/validators/lifecycle_callbacks_spec.rb +86 -0
- data/spec/models/validators/unique_validator_spec.rb +1 -0
- data/spec/page/path_string_renderer_spec.rb +5 -0
- data/spec/queries/live_query_spec.rb +16 -0
- data/spec/queries/query_association_splitter_spec.rb +14 -0
- data/spec/queries/query_diff_spec.rb +132 -0
- data/spec/queries/query_identifier_spec.rb +98 -0
- data/spec/queries/query_runner_spec.rb +63 -0
- data/spec/queries/query_tracker_spec.rb +141 -0
- data/spec/router/routes_spec.rb +52 -21
- data/spec/server/middleware/rack_content_types_spec.rb +78 -0
- data/spec/server/rack/asset_files_spec.rb +38 -30
- data/spec/spec_helper.rb +8 -0
- data/spec/utils/ejson_spec.rb +9 -8
- data/spec/utils/ejson_volt_time_spec.rb +65 -0
- data/templates/migration/migration.rb.tt +9 -0
- data/templates/newgem/gitignore.tt +1 -0
- data/templates/project/Gemfile.tt +19 -2
- data/templates/project/README.md.tt +6 -1
- data/templates/project/app/main/config/dependencies.rb +6 -0
- data/templates/project/config/app.rb.tt +18 -4
- data/volt.gemspec +2 -2
- metadata +73 -16
- data/app/volt/tasks/live_query/live_query_pool.rb +0 -48
- data/app/volt/tasks/live_query/query_tracker.rb +0 -92
- data/spec/tasks/live_query_spec.rb +0 -18
- data/spec/tasks/query_tasks.rb +0 -7
- data/spec/tasks/query_tracker_spec.rb +0 -145
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Volt::QueryIdentifier do
|
4
|
+
let(:ident) { subject }
|
5
|
+
it 'should call first on ident' do
|
6
|
+
expect(ident.name.to_query).to eq(["c", "ident", "name"])
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should group according to method calls' do
|
10
|
+
expect((ident.name < 5).to_query).to eq(["c", ["c", "ident", "name"], "<", 5])
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should group & into a Volt::QueryOp' do
|
14
|
+
query = ((ident.lat > 80) & (ident.lng < 50))
|
15
|
+
expect(query.to_query).to eq(
|
16
|
+
[
|
17
|
+
"c",
|
18
|
+
["c", ["c", "ident", "lat"], ">", 80],
|
19
|
+
"&",
|
20
|
+
["c", ["c", "ident", "lng"], "<", 50]
|
21
|
+
]
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should place the . correctly when coercing' do
|
26
|
+
query = (5 < ident.lat)
|
27
|
+
expect(query.to_query).to eq(["c", 5, "<", ["c", "ident", "lat"]])
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should group | into a Volt::QueryOp' do
|
31
|
+
query = ((ident.lat > 80) & (ident.lng < 50)) | (ident.name == 'Bob')
|
32
|
+
expect(query.to_query).to eq(
|
33
|
+
[
|
34
|
+
"c",
|
35
|
+
[
|
36
|
+
"c",
|
37
|
+
["c", ["c", "ident", "lat"], ">", 80],
|
38
|
+
'&',
|
39
|
+
["c",
|
40
|
+
["c", "ident", "lng"], "<", 50]
|
41
|
+
],
|
42
|
+
'|',
|
43
|
+
["c", ["c", "ident", "name"], "==", "Bob"]
|
44
|
+
]
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should handle negation with ~' do
|
49
|
+
query = ((ident.name == 'Ryan') & ~(ident.lat > 40))
|
50
|
+
expect(query.to_query).to eq(
|
51
|
+
[
|
52
|
+
"c",
|
53
|
+
["c", ["c", "ident", "name"], "==", "Ryan"],
|
54
|
+
"&",
|
55
|
+
["c",
|
56
|
+
["c", ["c", "ident", "lat"], ">", 40],
|
57
|
+
"~"
|
58
|
+
]
|
59
|
+
]
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should handle arrays as call arguments' do
|
64
|
+
query = (ident.name == [1,2,3])
|
65
|
+
expect(query.to_query).to eq(["c", ["c", "ident", "name"], "==", ["a", 1, 2, 3]])
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should handle =~' do
|
69
|
+
query = (ident.name =~ 'Bob')
|
70
|
+
expect(query.to_query).to eq(["c", ["c", "ident", "name"], "=~", "Bob"])
|
71
|
+
end
|
72
|
+
|
73
|
+
# This code fails until the following is fixed:
|
74
|
+
# https://github.com/opal/opal/issues/1138
|
75
|
+
# it 'should handle !~' do
|
76
|
+
# query = (ident.name !~ 'Bob')
|
77
|
+
# expect(query.to_query).to eq(["c", ["c", "ident", "name"], "!~", "Bob"])
|
78
|
+
# end
|
79
|
+
|
80
|
+
it 'should handle addition and comparison' do
|
81
|
+
query = (ident.pounds + 10 < 20)
|
82
|
+
expect(query.to_query).to eq(
|
83
|
+
[
|
84
|
+
"c",
|
85
|
+
[
|
86
|
+
"c",
|
87
|
+
["c", "ident", "pounds"],
|
88
|
+
"+",
|
89
|
+
10
|
90
|
+
],
|
91
|
+
"<",
|
92
|
+
20
|
93
|
+
]
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should handle method calls like max'
|
98
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
if RUBY_PLATFORM != 'opal'
|
4
|
+
class ::QPost < Volt::Model
|
5
|
+
has_many :q_comments
|
6
|
+
end
|
7
|
+
|
8
|
+
class ::QComment < Volt::Model
|
9
|
+
belongs_to :q_post
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Volt::QueryRunner do
|
13
|
+
it 'should run queries' do
|
14
|
+
data_store = double('data store')
|
15
|
+
|
16
|
+
query = [[:where, {user_id: 5}]]
|
17
|
+
|
18
|
+
result = [{id: 1, user_id: 5, title: 'Some post'}]
|
19
|
+
expect(data_store).to receive(:query).with('q_posts', query).and_return(result)
|
20
|
+
|
21
|
+
query_runner = Volt::QueryRunner.new(data_store, 'q_posts', query)
|
22
|
+
|
23
|
+
expect(query_runner.run).to eq(result)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should run sub queries' do
|
27
|
+
data_store = double('data store')
|
28
|
+
|
29
|
+
query = [[:where, {user_id: 5}], [:includes, :q_comments]]
|
30
|
+
|
31
|
+
result1 = [
|
32
|
+
{id: 1, user_id: 5, title: 'Some post'},
|
33
|
+
{id: 2, user_id: 5, title: 'Another Post'}
|
34
|
+
]
|
35
|
+
expect(data_store).to receive(:query).with(:q_posts, [[:where, {user_id: 5}]])
|
36
|
+
.and_return(result1)
|
37
|
+
|
38
|
+
query2 = [[:where, {:q_post_id=>[1, 2]}]]
|
39
|
+
|
40
|
+
result2 = [
|
41
|
+
{id: 4, q_post_id: 1, body: 'Some comment'},
|
42
|
+
{id: 5, q_post_id: 1, body: 'Another comment'},
|
43
|
+
{id: 6, q_post_id: 2, body: 'The best comment'}
|
44
|
+
]
|
45
|
+
expect(data_store).to receive(:query).with(:q_comments, query2)
|
46
|
+
.and_return(result2)
|
47
|
+
|
48
|
+
query_runner = Volt::QueryRunner.new(data_store, :q_posts, query)
|
49
|
+
|
50
|
+
result3 = [
|
51
|
+
{id: 1, user_id: 5, title: 'Some post', q_comments: [
|
52
|
+
{id: 4, q_post_id: 1, body: 'Some comment'},
|
53
|
+
{id: 5, q_post_id: 1, body: 'Another comment'}
|
54
|
+
]},
|
55
|
+
{id: 2, user_id: 5, title: 'Another Post', q_comments: [
|
56
|
+
{id: 6, q_post_id: 2, body: 'The best comment'}
|
57
|
+
]}
|
58
|
+
]
|
59
|
+
|
60
|
+
expect(query_runner.run).to eq(result3)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# if RUBY_PLATFORM != 'opal'
|
2
|
+
# describe 'LiveQuery' do
|
3
|
+
# # LiveQueryStub behaves as the front-end would with the changes to a
|
4
|
+
# # live query. Instead of passing changes to the models to the front
|
5
|
+
# # end, the changes are applied locally, then can be checked to see if
|
6
|
+
# # the correct transitions have taken place.
|
7
|
+
# class LiveQueryStub
|
8
|
+
# attr_reader :collection, :query, :items
|
9
|
+
# def initialize
|
10
|
+
# @collection = '_items'
|
11
|
+
# @query = {}
|
12
|
+
# @items = []
|
13
|
+
# end
|
14
|
+
|
15
|
+
# def notify_removed(ids, skip_channel)
|
16
|
+
# # Remove the id's that need to be removed
|
17
|
+
# @items.reject! { |item| ids.include?(item[:id]) }
|
18
|
+
# end
|
19
|
+
|
20
|
+
# def notify_added(index, data, skip_channel)
|
21
|
+
# @items.insert(index, data)
|
22
|
+
# end
|
23
|
+
|
24
|
+
# def notify_moved(id, index, skip_channel)
|
25
|
+
# item = @items.find { |item| item[:id] == id }
|
26
|
+
# @items.delete(item)
|
27
|
+
|
28
|
+
# @items.insert(index, item)
|
29
|
+
# end
|
30
|
+
|
31
|
+
# def notify_changed(id, data, skip_channel)
|
32
|
+
# item = @items.find { |item| item[:id] == id }
|
33
|
+
# idx = @items.index(item)
|
34
|
+
# @items.delete(item)
|
35
|
+
# @items.insert(idx, data)
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
|
39
|
+
# before do
|
40
|
+
# # Setup a live query stub
|
41
|
+
# @live_query = LiveQueryStub.new
|
42
|
+
# data_store = double('volt/data store')
|
43
|
+
|
44
|
+
# # return an empty collection
|
45
|
+
# @items = []
|
46
|
+
# expect(data_store).to receive(:query).at_least(:once) { @items.dup }
|
47
|
+
|
48
|
+
# @query_tracker = QueryTracker.new(@live_query, data_store)
|
49
|
+
# @query_tracker.run
|
50
|
+
# end
|
51
|
+
|
52
|
+
# it 'should add items' do
|
53
|
+
# @items = [
|
54
|
+
# { id: 1, name: 'one' }
|
55
|
+
# ]
|
56
|
+
|
57
|
+
# expect(@live_query.items).to eq([])
|
58
|
+
|
59
|
+
# @query_tracker.run
|
60
|
+
|
61
|
+
# expect(@live_query.items).to eq(@items)
|
62
|
+
# end
|
63
|
+
|
64
|
+
# it 'should remove items' do
|
65
|
+
# @items = [
|
66
|
+
# { id: 1, name: 'one' },
|
67
|
+
# { id: 2, name: 'two' }
|
68
|
+
# ]
|
69
|
+
# @query_tracker.run
|
70
|
+
# expect(@live_query.items).to eq(@items)
|
71
|
+
|
72
|
+
# @items = [
|
73
|
+
# { id: 2, name: 'two' }
|
74
|
+
# ]
|
75
|
+
# @query_tracker.run
|
76
|
+
# expect(@live_query.items).to eq(@items)
|
77
|
+
# end
|
78
|
+
|
79
|
+
# it 'should move items' do
|
80
|
+
# @items = [
|
81
|
+
# { id: 1, name: 'one' },
|
82
|
+
# { id: 2, name: 'two' },
|
83
|
+
# { id: 3, name: 'three' }
|
84
|
+
# ]
|
85
|
+
# @query_tracker.run
|
86
|
+
# expect(@live_query.items).to eq(@items)
|
87
|
+
|
88
|
+
# @items = [
|
89
|
+
# { id: 2, name: 'two' },
|
90
|
+
# { id: 3, name: 'three' },
|
91
|
+
# { id: 1, name: 'one' }
|
92
|
+
# ]
|
93
|
+
# @query_tracker.run
|
94
|
+
# expect(@live_query.items).to eq(@items)
|
95
|
+
# end
|
96
|
+
|
97
|
+
# it 'should handle complex transforms' do
|
98
|
+
# @items = [
|
99
|
+
# { id: 1, name: 'one' },
|
100
|
+
# { id: 2, name: 'two' },
|
101
|
+
# { id: 3, name: 'three' },
|
102
|
+
# { id: 4, name: 'four' },
|
103
|
+
# { id: 5, name: 'five' }
|
104
|
+
# ]
|
105
|
+
# @query_tracker.run
|
106
|
+
# expect(@live_query.items).to eq(@items)
|
107
|
+
|
108
|
+
# @items = [
|
109
|
+
# { id: 7, name: 'seven' },
|
110
|
+
# { id: 4, name: 'four' },
|
111
|
+
# { id: 1, name: 'one' },
|
112
|
+
# { id: 5, name: 'five' },
|
113
|
+
# { id: 3, name: 'three' },
|
114
|
+
# { id: 6, name: 'five' }
|
115
|
+
# ]
|
116
|
+
# @query_tracker.run
|
117
|
+
# expect(@live_query.items).to eq(@items)
|
118
|
+
# end
|
119
|
+
|
120
|
+
# it 'should notify data hash has changed' do
|
121
|
+
# @items = [
|
122
|
+
# { id: 1, name: 'one' },
|
123
|
+
# { id: 2, name: 'two' },
|
124
|
+
# { id: 3, name: 'three' },
|
125
|
+
# { id: 4, name: 'four' },
|
126
|
+
# { id: 5, name: 'five' }
|
127
|
+
# ]
|
128
|
+
# @query_tracker.run
|
129
|
+
# @items = [
|
130
|
+
# { id: 1, name: 'some' },
|
131
|
+
# { id: 2, name: 'values' },
|
132
|
+
# { id: 3, name: 'have' },
|
133
|
+
# { id: 4, name: 'changed' },
|
134
|
+
# { id: 5, name: 'other' }
|
135
|
+
# ]
|
136
|
+
# expect(@live_query.items).to_not eq(@items)
|
137
|
+
# @query_tracker.run
|
138
|
+
# expect(@live_query.items).to eq(@items)
|
139
|
+
# end
|
140
|
+
# end
|
141
|
+
# end
|
data/spec/router/routes_spec.rb
CHANGED
@@ -63,18 +63,22 @@ describe Volt::Routes do
|
|
63
63
|
end
|
64
64
|
|
65
65
|
param_matches = @routes.instance_variable_get(:@param_matches)
|
66
|
-
expect(param_matches[:client].map { |v| v[0] }).to eq(
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
66
|
+
expect(param_matches[:client].map { |v| v[0] }).to eq(
|
67
|
+
[
|
68
|
+
{ view: 'blog' },
|
69
|
+
{ view: 'blog/show', id: nil },
|
70
|
+
{ view: 'blog/edit', id: nil },
|
71
|
+
{ view: 'blog/tag', tag: nil },
|
72
|
+
{ view: 'login', action: 'user', name: nil, id: nil }
|
73
|
+
]
|
74
|
+
)
|
75
|
+
|
76
|
+
expect(param_matches[:get].map { |v| v[0] }).to eq(
|
77
|
+
[
|
78
|
+
{ controller: 'articles', action: 'index' },
|
79
|
+
{ controller: 'articles', action: 'show', id: nil }
|
80
|
+
]
|
81
|
+
)
|
78
82
|
end
|
79
83
|
|
80
84
|
it 'should match routes' do
|
@@ -92,6 +96,10 @@ describe Volt::Routes do
|
|
92
96
|
put '/people', controller: 'people', action: 'update'
|
93
97
|
patch '/people/1', controller: 'people', action: 'update'
|
94
98
|
delete '/people/2', controller: 'people', action: 'destroy'
|
99
|
+
client '/pics/new/{{ new_id }}/two', controller: 'pics', action: 'new'
|
100
|
+
client '/pics/{{ pic_id }}/view/one', controller: 'pics', action: 'view'
|
101
|
+
client '/pics/{{ *pic_id }}', controller: 'pics', action: 'show'
|
102
|
+
get '/wide_match/{{ *path_parts }}', controller: 'wide_match', action: 'show'
|
95
103
|
end
|
96
104
|
|
97
105
|
params = @routes.url_to_params('/blog')
|
@@ -122,7 +130,7 @@ describe Volt::Routes do
|
|
122
130
|
expect(params).to eq(controller: 'articles', action: 'index')
|
123
131
|
|
124
132
|
params = @routes.url_to_params(:post, '/articles')
|
125
|
-
expect(params).to
|
133
|
+
expect(params).to eq(false)
|
126
134
|
|
127
135
|
params = @routes.url_to_params(:post, '/comments')
|
128
136
|
expect(params).to eq(controller: 'comments', action: 'create')
|
@@ -141,6 +149,29 @@ describe Volt::Routes do
|
|
141
149
|
|
142
150
|
params = @routes.url_to_params(:put, '/articles/2/comments/9')
|
143
151
|
expect(params).to eq(controller: 'comments', action: 'update', articles_id: '2', id: '9')
|
152
|
+
|
153
|
+
params = @routes.url_to_params('/pics/new/view/one')
|
154
|
+
expect(params).to eq({controller: "pics", action: "view", pic_id: "new"})
|
155
|
+
|
156
|
+
params = @routes.url_to_params('/pics/new/view/two')
|
157
|
+
expect(params).to eq({controller: "pics", action: "new", new_id: "view"})
|
158
|
+
|
159
|
+
params = @routes.url_to_params('/pics/new/view/three')
|
160
|
+
expect(params).to eq({controller: "pics", action: "show", pic_id: "new/view/three"})
|
161
|
+
|
162
|
+
params = @routes.url_to_params(:get, '/wide_match/some/image/path/file.png')
|
163
|
+
expect(params).to eq({controller: "wide_match", action: "show", path_parts: "some/image/path/file.png"})
|
164
|
+
|
165
|
+
params = @routes.url_to_params(:get, '/wide_match/http://something/cool.jpg')
|
166
|
+
expect(params).to eq({controller: "wide_match", action: "show", path_parts: "http://something/cool.jpg"})
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'should raise an error if the splat match isn\'t at the end of the url' do
|
170
|
+
expect do
|
171
|
+
routes do
|
172
|
+
client '/blog/{{ *slug }}/after', view: 'blog'
|
173
|
+
end
|
174
|
+
end.to raise_error('The splat (*) operator can only be used at the end of a url')
|
144
175
|
end
|
145
176
|
|
146
177
|
it 'should go from params to url' do
|
@@ -279,16 +310,16 @@ describe Volt::Routes do
|
|
279
310
|
params = @routes.url_to_params(:get, '/api/v1/articles/1')
|
280
311
|
expect(params).to eq(controller: 'articles', action: 'show', id: '1')
|
281
312
|
|
282
|
-
expect(@routes.url_to_params(:post, '/api/v1/articles')).to
|
283
|
-
expect(@routes.url_to_params(:put, '/api/v1/articles/1')).to
|
284
|
-
expect(@routes.url_to_params(:delete, '/api/v1/articles/1')).to
|
313
|
+
expect(@routes.url_to_params(:post, '/api/v1/articles')).to eq(false)
|
314
|
+
expect(@routes.url_to_params(:put, '/api/v1/articles/1')).to eq(false)
|
315
|
+
expect(@routes.url_to_params(:delete, '/api/v1/articles/1')).to eq(false)
|
285
316
|
|
286
317
|
routes do
|
287
318
|
rest '/api/v1/articles', controller: 'articles', only: [:update, :destroy, :create]
|
288
319
|
end
|
289
320
|
|
290
|
-
expect(@routes.url_to_params(:get, '/api/v1/articles')).to
|
291
|
-
expect(@routes.url_to_params(:get, '/api/v1/articles/1')).to
|
321
|
+
expect(@routes.url_to_params(:get, '/api/v1/articles')).to eq(false)
|
322
|
+
expect(@routes.url_to_params(:get, '/api/v1/articles/1')).to eq(false)
|
292
323
|
|
293
324
|
params = @routes.url_to_params(:post, '/api/v1/articles')
|
294
325
|
expect(params).to eq(controller: 'articles', action: 'create')
|
@@ -311,8 +342,8 @@ describe Volt::Routes do
|
|
311
342
|
params = @routes.url_to_params(:get, '/api/v1/articles/1')
|
312
343
|
expect(params).to eq(controller: 'articles', action: 'show', id: '1')
|
313
344
|
|
314
|
-
expect(@routes.url_to_params(:post, '/api/v1/articles')).to
|
315
|
-
expect(@routes.url_to_params(:put, '/api/v1/articles/1')).to
|
316
|
-
expect(@routes.url_to_params(:delete, '/api/v1/articles/1')).to
|
345
|
+
expect(@routes.url_to_params(:post, '/api/v1/articles')).to eq(false)
|
346
|
+
expect(@routes.url_to_params(:put, '/api/v1/articles/1')).to eq(false)
|
347
|
+
expect(@routes.url_to_params(:delete, '/api/v1/articles/1')).to eq(false)
|
317
348
|
end
|
318
349
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
if RUBY_PLATFORM != 'opal'
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Rack::HttpContentTypes do
|
5
|
+
include Rack::Test::Methods
|
6
|
+
|
7
|
+
let(:app) { Volt.current_app.middleware }
|
8
|
+
|
9
|
+
describe 'with default parser' do
|
10
|
+
it "allows you to setup parsers for content types" do
|
11
|
+
middleware = Rack::HttpContentTypes.new Volt, :parsers => { 'foo' => 'bar' }
|
12
|
+
expect(middleware.parsers['foo']).to eq('bar')
|
13
|
+
end
|
14
|
+
|
15
|
+
it "allows you to setup error handlers" do
|
16
|
+
middleware = Rack::HttpContentTypes.new Volt, :handlers => { 'foo' => 'bar' }
|
17
|
+
expect(middleware.handlers['foo']).to eq('bar')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses params from Content-Type: application/json" do
|
21
|
+
payload = JSON.dump(:a => 1)
|
22
|
+
post '/simple_http', payload, { 'CONTENT_TYPE' => 'application/json' }
|
23
|
+
expect(last_response).to be_ok
|
24
|
+
expect(last_response.body).to match(/a: 1/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not handle params from unknown Content-type" do
|
28
|
+
payload = JSON.dump(:a => 1)
|
29
|
+
post '/simple_http', payload, { 'CONTENT_TYPE' => 'application/unknown' }
|
30
|
+
expect(last_response).to be_ok
|
31
|
+
expect(last_response.body).to_not match(/a: 1/)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "matches Content-Type by regex" do
|
35
|
+
payload = JSON.dump(:a => 1)
|
36
|
+
post '/simple_http', payload, { 'CONTENT_TYPE' => 'application/vnd.foo+json' }
|
37
|
+
expect(last_response).to be_ok
|
38
|
+
expect(last_response.body).to match(/a: 1/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "handles custom json parser" do
|
42
|
+
Volt.setup do |config|
|
43
|
+
config.http_content_types = {
|
44
|
+
parsers:{
|
45
|
+
'application/json' => proc { |body| {'rick_says' => 'never gonna let you down'} }
|
46
|
+
}
|
47
|
+
}
|
48
|
+
end
|
49
|
+
payload = JSON.dump(:a => 1)
|
50
|
+
post '/simple_http', payload, { 'CONTENT_TYPE' => 'application/json' }
|
51
|
+
expect(last_response).to be_ok
|
52
|
+
expect(last_response.body).to match(/never gonna let you down/)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'with custom parser' do
|
57
|
+
before do
|
58
|
+
Volt.setup do |config|
|
59
|
+
config.http_content_types = {
|
60
|
+
parsers: {
|
61
|
+
'application/roll' => proc { |body| {'rick_says' => 'never gonna give you up'}}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it "handles custom content types" do
|
68
|
+
#see spec/apps/kitchen_sink/config/app.rb
|
69
|
+
payload = JSON.dump(:a => 1)
|
70
|
+
post '/simple_http', payload, { 'CONTENT_TYPE' => 'application/roll' }
|
71
|
+
expect(last_response).to be_ok
|
72
|
+
expect(last_response.body).to match(/never gonna give you up/)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|